AST Types
This commit is contained in:
+75
-13
@@ -7,12 +7,21 @@ uses
|
||||
System.Generics.Collections,
|
||||
System.Classes,
|
||||
Myc.Data.Value,
|
||||
Myc.Ast.Nodes;
|
||||
Myc.Ast.Nodes,
|
||||
Myc.Ast.Types;
|
||||
|
||||
type
|
||||
IExecutionScope = interface;
|
||||
IScopeDescriptor = interface;
|
||||
|
||||
// A resolved symbol, containing its runtime address and static type.
|
||||
TResolvedSymbol = record
|
||||
Address: TResolvedAddress;
|
||||
StaticType: IStaticType;
|
||||
constructor Create(const AAddress: TResolvedAddress; const AStaticType: IStaticType);
|
||||
class operator Initialize(out Dest: TResolvedSymbol);
|
||||
end;
|
||||
|
||||
IValueCell = interface
|
||||
{$region 'private'}
|
||||
function GetValue: TDataValue;
|
||||
@@ -52,11 +61,16 @@ type
|
||||
function GetParent: IScopeDescriptor;
|
||||
function GetSlotCount: Integer;
|
||||
function GetSymbols: TDictionary<string, Integer>;
|
||||
function GetType(SlotIndex: Integer): IStaticType;
|
||||
{$endregion}
|
||||
function CreateScope(const AParent: IExecutionScope): IExecutionScope;
|
||||
function Define(const Name: string): Integer;
|
||||
// Defines a symbol, returns its slot index.
|
||||
function Define(const Name: string; const AType: IStaticType): Integer;
|
||||
// Updates the type of an already defined symbol (e.g., for lambda self-reference).
|
||||
procedure UpdateType(SlotIndex: Integer; const AType: IStaticType);
|
||||
procedure DefineMacro(const Name: string; const Node: IMacroDefinitionNode);
|
||||
function FindSymbol(const Name: string): TResolvedAddress;
|
||||
// Finds a symbol, returns its address and type.
|
||||
function FindSymbol(const Name: string): TResolvedSymbol;
|
||||
function FindMacro(const Name: string): IMacroDefinitionNode;
|
||||
property Parent: IScopeDescriptor read GetParent;
|
||||
property SlotCount: Integer read GetSlotCount;
|
||||
@@ -129,6 +143,7 @@ type
|
||||
property NameStrings: TList<string> read FNameStrings;
|
||||
property NameToIndex: TDictionary<Integer, Integer> read GetNameToIndex;
|
||||
property Parent: IExecutionScope read FParent;
|
||||
property ValuesArray: TArray<TScopeItem> read FValues; // Expose FValues for PopulateFromScope
|
||||
end;
|
||||
|
||||
TScopeDescriptor = class(TInterfacedObject, IScopeDescriptor)
|
||||
@@ -136,22 +151,39 @@ type
|
||||
FParent: IScopeDescriptor;
|
||||
FSymbols: TDictionary<string, Integer>;
|
||||
FMacros: TDictionary<string, IMacroDefinitionNode>;
|
||||
FSlotTypes: TArray<IStaticType>; // Stores types by SlotIndex
|
||||
function GetParent: IScopeDescriptor;
|
||||
function GetSlotCount: Integer;
|
||||
function GetSymbols: TDictionary<string, Integer>;
|
||||
function GetType(SlotIndex: Integer): IStaticType;
|
||||
public
|
||||
constructor Create(const AParent: IScopeDescriptor);
|
||||
destructor Destroy; override;
|
||||
class function CreateDescriptor(const Scope: IExecutionScope): IScopeDescriptor; static;
|
||||
function Define(const Name: string): Integer;
|
||||
function Define(const Name: string; const AType: IStaticType): Integer;
|
||||
procedure UpdateType(SlotIndex: Integer; const AType: IStaticType);
|
||||
procedure DefineMacro(const Name: string; const Node: IMacroDefinitionNode);
|
||||
function FindSymbol(const Name: string): TResolvedAddress;
|
||||
function FindSymbol(const Name: string): TResolvedSymbol;
|
||||
function FindMacro(const Name: string): IMacroDefinitionNode;
|
||||
function CreateScope(const Parent: IExecutionScope): IExecutionScope;
|
||||
procedure PopulateFromScope(Scope: TExecutionScope);
|
||||
property Symbols: TDictionary<string, Integer> read FSymbols;
|
||||
end;
|
||||
|
||||
{ TResolvedSymbol }
|
||||
|
||||
constructor TResolvedSymbol.Create(const AAddress: TResolvedAddress; const AStaticType: IStaticType);
|
||||
begin
|
||||
Address := AAddress;
|
||||
StaticType := AStaticType;
|
||||
end;
|
||||
|
||||
class operator TResolvedSymbol.Initialize(out Dest: TResolvedSymbol);
|
||||
begin
|
||||
// TResolvedAddress has its own Initialize operator
|
||||
Dest.StaticType := TTypes.Unknown;
|
||||
end;
|
||||
|
||||
{ TExecutionScope.TValueCell }
|
||||
|
||||
constructor TExecutionScope.TValueCell.Create(const AValue: TDataValue);
|
||||
@@ -460,10 +492,12 @@ begin
|
||||
FParent := AParent;
|
||||
FSymbols := TDictionary<string, Integer>.Create;
|
||||
FMacros := TDictionary<string, IMacroDefinitionNode>.Create;
|
||||
FSlotTypes := [];
|
||||
end;
|
||||
|
||||
destructor TScopeDescriptor.Destroy;
|
||||
begin
|
||||
FSlotTypes := nil;
|
||||
FMacros.Free;
|
||||
FSymbols.Free;
|
||||
inherited;
|
||||
@@ -486,10 +520,19 @@ begin
|
||||
Result := TExecutionScope.Create(Parent, Self, nil);
|
||||
end;
|
||||
|
||||
function TScopeDescriptor.Define(const Name: string): Integer;
|
||||
function TScopeDescriptor.Define(const Name: string; const AType: IStaticType): Integer;
|
||||
begin
|
||||
Result := FSymbols.Count;
|
||||
FSymbols.Add(Name, Result);
|
||||
SetLength(FSlotTypes, Result + 1);
|
||||
FSlotTypes[Result] := AType;
|
||||
end;
|
||||
|
||||
procedure TScopeDescriptor.UpdateType(SlotIndex: Integer; const AType: IStaticType);
|
||||
begin
|
||||
if (SlotIndex < 0) or (SlotIndex >= Length(FSlotTypes)) then
|
||||
raise EArgumentOutOfRangeException.Create('Invalid SlotIndex in UpdateType.');
|
||||
FSlotTypes[SlotIndex] := AType;
|
||||
end;
|
||||
|
||||
procedure TScopeDescriptor.DefineMacro(const Name: string; const Node: IMacroDefinitionNode);
|
||||
@@ -512,21 +555,25 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TScopeDescriptor.FindSymbol(const Name: string): TResolvedAddress;
|
||||
function TScopeDescriptor.FindSymbol(const Name: string): TResolvedSymbol;
|
||||
var
|
||||
currentDescriptor: IScopeDescriptor;
|
||||
slotIndex: Integer;
|
||||
begin
|
||||
Result.Kind := akUnresolved;
|
||||
Result.ScopeDepth := 0;
|
||||
Result.Address.Kind := akUnresolved;
|
||||
Result.Address.ScopeDepth := 0;
|
||||
Result.StaticType := TTypes.Unknown;
|
||||
currentDescriptor := Self;
|
||||
while Assigned(currentDescriptor) do
|
||||
begin
|
||||
if currentDescriptor.Symbols.TryGetValue(Name, Result.SlotIndex) then
|
||||
if currentDescriptor.Symbols.TryGetValue(Name, slotIndex) then
|
||||
begin
|
||||
Result.Kind := akLocalOrParent;
|
||||
Result.Address.Kind := akLocalOrParent;
|
||||
Result.Address.SlotIndex := slotIndex;
|
||||
Result.StaticType := currentDescriptor.GetType(slotIndex);
|
||||
exit;
|
||||
end;
|
||||
inc(Result.ScopeDepth);
|
||||
inc(Result.Address.ScopeDepth);
|
||||
currentDescriptor := currentDescriptor.Parent;
|
||||
end;
|
||||
end;
|
||||
@@ -546,11 +593,23 @@ begin
|
||||
Result := FSymbols;
|
||||
end;
|
||||
|
||||
function TScopeDescriptor.GetType(SlotIndex: Integer): IStaticType;
|
||||
begin
|
||||
if (SlotIndex < 0) or (SlotIndex >= Length(FSlotTypes)) then
|
||||
raise EArgumentOutOfRangeException.Create('Invalid SlotIndex in GetType.');
|
||||
Result := FSlotTypes[SlotIndex];
|
||||
end;
|
||||
|
||||
procedure TScopeDescriptor.PopulateFromScope(Scope: TExecutionScope);
|
||||
var
|
||||
val: TDataValue;
|
||||
i: Integer;
|
||||
begin
|
||||
// Recreate descriptor by iterating all defined symbols in the runtime scope.
|
||||
SetLength(FSlotTypes, Length(Scope.ValuesArray)); // Size the array
|
||||
for i := 0 to High(FSlotTypes) do
|
||||
FSlotTypes[i] := TTypes.Unknown; // Fill with Unknown
|
||||
|
||||
for var pair in Scope.NameToIndex do
|
||||
begin
|
||||
var name := Scope.NameStrings[pair.Key];
|
||||
@@ -560,8 +619,11 @@ begin
|
||||
if not FSymbols.ContainsKey(name) then
|
||||
FSymbols.Add(name, slotIndex);
|
||||
|
||||
// We cannot recover the static type from the runtime scope.
|
||||
// FSlotTypes[slotIndex] remains TTypes.Unknown.
|
||||
|
||||
// Check if the symbol is also a macro and add it to the macro table.
|
||||
val := Scope.FValues[slotIndex].Value;
|
||||
val := Scope.ValuesArray[slotIndex].Value;
|
||||
if (val.Kind = vkInterface) and (val.AsIntf<IAstNode> is TMacroDefinitionNode) then
|
||||
begin
|
||||
if not FMacros.ContainsKey(name) then
|
||||
|
||||
Reference in New Issue
Block a user