This commit is contained in:
Michael Schimmel
2025-10-30 15:23:34 +01:00
parent 1394314a57
commit dfe1f04333
6 changed files with 130 additions and 8 deletions
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -20,7 +20,8 @@ uses
Myc.Fmx.AstEditor.Text in 'Myc.Fmx.AstEditor.Text.pas',
Myc.Utils in '..\Src\Myc.Utils.pas',
Myc.Ast.Script in '..\Src\AST\Myc.Ast.Script.pas',
Myc.Ast.Types in '..\Src\AST\Myc.Ast.Types.pas';
Myc.Ast.Types in '..\Src\AST\Myc.Ast.Types.pas',
Myc.Data.Keyword in '..\Src\Data\Myc.Data.Keyword.pas';
{$R *.res}
+1
View File
@@ -151,6 +151,7 @@
<DCCReference Include="..\Src\Myc.Utils.pas"/>
<DCCReference Include="..\Src\AST\Myc.Ast.Script.pas"/>
<DCCReference Include="..\Src\AST\Myc.Ast.Types.pas"/>
<DCCReference Include="..\Src\Data\Myc.Data.Keyword.pas"/>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
+1 -1
View File
@@ -297,7 +297,7 @@ begin
key := argScalar.Value.AsInt64;
var cache := cCache.AsObject as TDictionary<Int64, TDataValue>;
var cache := TDictionary<Int64, TDataValue>(cCache.AsObject);
if cache.TryGetValue(key, Result) then
exit;
+83
View File
@@ -0,0 +1,83 @@
unit Myc.Data.Keyword;
interface
uses
System.SysUtils,
System.Classes,
System.Generics.Collections,
System.SyncObjs;
type
// The runtime representation of an interned keyword
IKeyword = interface(IInterface)
function GetName: string;
property Name: string read GetName;
end;
// Factory and registry for all keywords (Flyweight Pattern)
TKeywordRegistry = record
strict private
type
TKeyword = class(TInterfacedObject, IKeyword)
private
FName: string;
function GetName: string;
public
constructor Create(const AName: string);
end;
strict private
class var
FLock: TSpinLock;
class var
FRegistry: TDictionary<string, IKeyword>;
class constructor Create;
class destructor Destroy;
public
// Gets or creates the interned keyword for the given name.
class function Intern(const AName: string): IKeyword; static;
end;
implementation
{ TKeywordRegistry.TKeyword }
constructor TKeywordRegistry.TKeyword.Create(const AName: string);
begin
inherited Create;
FName := AName;
end;
function TKeywordRegistry.TKeyword.GetName: string;
begin
Result := FName;
end;
{ TKeywordRegistry }
class constructor TKeywordRegistry.Create;
begin
FLock := TSpinLock.Create(false);
FRegistry := TDictionary<string, IKeyword>.Create;
end;
class destructor TKeywordRegistry.Destroy;
begin
FRegistry.Free;
end;
class function TKeywordRegistry.Intern(const AName: string): IKeyword;
begin
FLock.Enter;
try
if not FRegistry.TryGetValue(AName, Result) then
begin
Result := TKeyword.Create(AName);
FRegistry.Add(AName, Result);
end;
finally
FLock.Exit;
end;
end;
end.
+42 -5
View File
@@ -7,11 +7,24 @@ uses
System.SyncObjs,
Myc.Utils,
Myc.Data.Scalar,
Myc.Data.Series;
Myc.Data.Series,
Myc.Data.Keyword;
type
TDataValueKind =
(vkVoid, vkScalar, vkText, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkPointer, vkGeneric);
TDataValueKind = (
vkVoid,
vkScalar,
vkText,
vkKeyword,
vkSeries,
vkRecordSeries,
vkRecord,
vkManagedObject,
vkMethod,
vkInterface,
vkPointer,
vkGeneric
);
TDataValue = record
type
@@ -47,6 +60,7 @@ type
class operator Implicit(const AValue: TScalar): TDataValue; overload; inline;
class operator Implicit(const AValue: TDataValue): TScalar; overload; inline;
class operator Implicit(const AValue: String): TDataValue; overload; inline;
class operator Implicit(const AValue: IKeyword): TDataValue; overload; inline;
class operator Implicit(const AValue: TDataValue.TFunc): TDataValue; overload; inline;
class operator Implicit(const AValue: TObject): TDataValue; overload; inline;
@@ -68,10 +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
function AsScalar: TScalar; inline;
function AsMethod: TFunc; inline;
function AsText: String; inline;
function AsKeyword: IKeyword; inline; // Added
function AsRecordSeries: IRecordSeries; inline;
function AsRecord: TScalarRecord; inline;
function AsSeries: ISeries; inline;
@@ -171,6 +187,13 @@ begin
Result := Pointer(FScalar.Value.AsInt64);
end;
function TDataValue.AsKeyword: IKeyword;
begin
if (FKind <> vkKeyword) then
raise EInvalidCast.Create('Cannot read value as Keyword.');
Result := IKeyword(FInterface);
end;
function TDataValue.AsRecord: TScalarRecord;
begin
if (FKind <> vkRecord) then
@@ -241,7 +264,7 @@ begin
TInterlocked.CompareExchange(FScalar.Value.AsInt64, NewValue.AsScalar.Value.AsInt64, Expected.AsScalar.Value.AsInt64)
= Expected.AsScalar.Value.AsInt64;
vkText, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric:
vkText, vkKeyword, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric: // Added vkKeyword
Result := IntfCompareExchange(FInterface, NewValue.FInterface, Expected.FInterface) = Expected.FInterface;
end;
end;
@@ -258,6 +281,12 @@ begin
Result.FInterface := TVal<T>.Create(AValue);
end;
class function TDataValue.FromKeyword(const AValue: IKeyword): TDataValue;
begin
Result.FKind := vkKeyword;
Result.FInterface := AValue;
end;
class function TDataValue.FromPtr(const AValue: Pointer): TDataValue;
begin
Assert(sizeof(Pointer) <= sizeof(Int64));
@@ -296,6 +325,12 @@ begin
Result.FInterface := TVal<String>.Create(AValue);
end;
class operator TDataValue.Implicit(const AValue: IKeyword): TDataValue;
begin
Result.FKind := vkKeyword;
Result.FInterface := AValue;
end;
function TDataValue.GetIsVoid: Boolean;
begin
Result := FKind = vkVoid;
@@ -334,7 +369,7 @@ begin
end;
vkPointer: Result := TInterlocked.Exchange(FScalar.Value.AsInt64, NewValue.AsScalar.Value.AsInt64);
vkText, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric:
vkText, vkKeyword, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric: // Added vkKeyword
begin
Result.FKind := FKind;
Result.FInterface := IntfExchange(FInterface, NewValue.FInterface);
@@ -351,6 +386,7 @@ begin
case FKind of
vkScalar: Result := FScalar.ToString;
vkText: Result := '"' + AsText + '"';
vkKeyword: Result := ':' + AsKeyword.Name; // Added
vkSeries:
begin
var series := AsSeries;
@@ -454,6 +490,7 @@ begin
vkVoid: Result := 'Void';
vkScalar: Result := 'Scalar';
vkText: Result := 'Text';
vkKeyword: Result := 'Keyword'; // Added
vkSeries: Result := 'Series';
vkRecordSeries: Result := 'RecordSeries';
vkRecord: Result := 'Record';