Resolved dependency between AST nodes and scope
This commit is contained in:
@@ -214,11 +214,10 @@ end;
|
|||||||
|
|
||||||
function TForm1.CompileAst(const ANode: IAstNode; const AParentScope: IExecutionScope; out ADescriptor: IScopeDescriptor): IAstNode;
|
function TForm1.CompileAst(const ANode: IAstNode; const AParentScope: IExecutionScope; out ADescriptor: IScopeDescriptor): IAstNode;
|
||||||
var
|
var
|
||||||
macroDescriptor: IScopeDescriptor;
|
|
||||||
expandedAst, boundAst, typedAst, loweredAst: IAstNode;
|
expandedAst, boundAst, typedAst, loweredAst: IAstNode;
|
||||||
begin
|
begin
|
||||||
// Step 1: Expand macros (Phase 1)
|
// Step 1: Expand macros (Phase 1)
|
||||||
expandedAst := TMacroExpander.ExpandMacros(AParentScope, ANode, macroDescriptor, CreateEvaluator);
|
expandedAst := TMacroExpander.ExpandMacros(AParentScope, ANode, CreateEvaluator);
|
||||||
|
|
||||||
// Step 2: Bind names and addresses (Phase 2)
|
// Step 2: Bind names and addresses (Phase 2)
|
||||||
boundAst := TAstBinder.Bind(AParentScope, expandedAst, ADescriptor);
|
boundAst := TAstBinder.Bind(AParentScope, expandedAst, ADescriptor);
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ uses
|
|||||||
System.SysUtils,
|
System.SysUtils,
|
||||||
System.Classes,
|
System.Classes,
|
||||||
System.Generics.Collections,
|
System.Generics.Collections,
|
||||||
Myc.Ast.Nodes,
|
|
||||||
Myc.Ast.Visitor,
|
Myc.Ast.Visitor,
|
||||||
Myc.Data.Value,
|
Myc.Data.Value,
|
||||||
Myc.Data.Scalar,
|
Myc.Data.Scalar,
|
||||||
|
Myc.Ast.Nodes,
|
||||||
|
Myc.Ast.Scope,
|
||||||
Myc.Ast;
|
Myc.Ast;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
//==================================================================================================
|
|
||||||
//== FULL UNIT START: Myc.Ast.MacroExpander (from Myc.Ast.MacroExpander.pas)
|
|
||||||
//==================================================================================================
|
|
||||||
unit Myc.Ast.MacroExpander;
|
unit Myc.Ast.MacroExpander;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
@@ -19,7 +16,8 @@ uses
|
|||||||
|
|
||||||
type
|
type
|
||||||
IAstMacroExpander = interface(IAstVisitor)
|
IAstMacroExpander = interface(IAstVisitor)
|
||||||
function Execute(const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
|
// Signatur geändert: Descriptor wird nicht mehr zurückgegeben
|
||||||
|
function Execute(const RootNode: IAstNode): IAstNode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Callback type for compile-time evaluation of Unquote expressions
|
// Callback type for compile-time evaluation of Unquote expressions
|
||||||
@@ -48,10 +46,29 @@ type
|
|||||||
// This transformer traverses the entire AST *before* the binder,
|
// This transformer traverses the entire AST *before* the binder,
|
||||||
// to find and expand macros.
|
// to find and expand macros.
|
||||||
TMacroExpander = class(TAstTransformer, IAstMacroExpander)
|
TMacroExpander = class(TAstTransformer, IAstMacroExpander)
|
||||||
|
type
|
||||||
|
TMacroRegistry = class
|
||||||
|
private
|
||||||
|
FParent: TMacroRegistry;
|
||||||
|
FMacros: TDictionary<string, IMacroDefinitionNode>;
|
||||||
|
public
|
||||||
|
constructor Create(AParent: TMacroRegistry);
|
||||||
|
destructor Destroy; override;
|
||||||
|
procedure Define(const Name: string; const Node: IMacroDefinitionNode);
|
||||||
|
function Find(const Name: string): IMacroDefinitionNode;
|
||||||
|
end;
|
||||||
|
|
||||||
private
|
private
|
||||||
FInitialScope: IExecutionScope;
|
FInitialScope: IExecutionScope;
|
||||||
FCurrentDescriptor: IScopeDescriptor;
|
|
||||||
|
// Ersetzt FCurrentDescriptor
|
||||||
|
FCurrentMacroRegistry: TMacroRegistry;
|
||||||
|
|
||||||
FEvaluatorFactory: TEvaluatorFactory;
|
FEvaluatorFactory: TEvaluatorFactory;
|
||||||
|
|
||||||
|
procedure EnterMacroScope;
|
||||||
|
procedure ExitMacroScope;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
// Finds macro definitions
|
// Finds macro definitions
|
||||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; override;
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; override;
|
||||||
@@ -60,14 +77,21 @@ type
|
|||||||
function VisitQuasiquote(const Node: IQuasiquoteNode): IAstNode; override;
|
function VisitQuasiquote(const Node: IQuasiquoteNode): IAstNode; override;
|
||||||
function VisitUnquote(const Node: IUnquoteNode): IAstNode; override;
|
function VisitUnquote(const Node: IUnquoteNode): IAstNode; override;
|
||||||
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): IAstNode; override;
|
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): IAstNode; override;
|
||||||
|
|
||||||
|
// NEU: Überschrieben für lexikalisches Makro-Scoping
|
||||||
|
function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
|
||||||
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create(const AInitialScope: IExecutionScope; const AEvaluatorFactory: TEvaluatorFactory);
|
constructor Create(const AInitialScope: IExecutionScope; const AEvaluatorFactory: TEvaluatorFactory);
|
||||||
function Execute(const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
|
destructor Destroy; override;
|
||||||
|
|
||||||
|
// Signatur geändert
|
||||||
|
function Execute(const RootNode: IAstNode): IAstNode;
|
||||||
|
|
||||||
class function ExpandMacros(
|
class function ExpandMacros(
|
||||||
const InitialScope: IExecutionScope;
|
const InitialScope: IExecutionScope;
|
||||||
const RootNode: IAstNode;
|
const RootNode: IAstNode;
|
||||||
out Descriptor: IScopeDescriptor;
|
|
||||||
const EvaluatorFactory: TEvaluatorFactory
|
const EvaluatorFactory: TEvaluatorFactory
|
||||||
): IAstNode; static;
|
): IAstNode; static;
|
||||||
end;
|
end;
|
||||||
@@ -80,6 +104,40 @@ uses
|
|||||||
Myc.Ast.Evaluator, // Required for TEvaluatorVisitor.Execute
|
Myc.Ast.Evaluator, // Required for TEvaluatorVisitor.Execute
|
||||||
Myc.Data.Keyword;
|
Myc.Data.Keyword;
|
||||||
|
|
||||||
|
{ TMacroRegistry }
|
||||||
|
|
||||||
|
constructor TMacroExpander.TMacroRegistry.Create(AParent: TMacroRegistry);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FParent := AParent;
|
||||||
|
FMacros := TDictionary<string, IMacroDefinitionNode>.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TMacroExpander.TMacroRegistry.Destroy;
|
||||||
|
begin
|
||||||
|
FMacros.Free;
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMacroExpander.TMacroRegistry.Define(const Name: string; const Node: IMacroDefinitionNode);
|
||||||
|
begin
|
||||||
|
FMacros.AddOrSetValue(Name, Node);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMacroExpander.TMacroRegistry.Find(const Name: string): IMacroDefinitionNode;
|
||||||
|
var
|
||||||
|
current: TMacroRegistry;
|
||||||
|
begin
|
||||||
|
current := Self;
|
||||||
|
while Assigned(current) do
|
||||||
|
begin
|
||||||
|
if current.FMacros.TryGetValue(Name, Result) then
|
||||||
|
exit;
|
||||||
|
current := current.FParent;
|
||||||
|
end;
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TExpansionVisitor }
|
{ TExpansionVisitor }
|
||||||
|
|
||||||
constructor TExpansionVisitor.Create(const AMacroScope: IExecutionScope; const AEvaluate: TEvaluateProc);
|
constructor TExpansionVisitor.Create(const AMacroScope: IExecutionScope; const AEvaluate: TEvaluateProc);
|
||||||
@@ -232,22 +290,44 @@ begin
|
|||||||
Assert(Assigned(AEvaluatorFactory));
|
Assert(Assigned(AEvaluatorFactory));
|
||||||
FInitialScope := AInitialScope;
|
FInitialScope := AInitialScope;
|
||||||
FEvaluatorFactory := AEvaluatorFactory;
|
FEvaluatorFactory := AEvaluatorFactory;
|
||||||
// Create the top-level descriptor for macros
|
|
||||||
FCurrentDescriptor := AInitialScope.CreateDescriptor;
|
// Erzeugt die Root-Registry für Makros
|
||||||
|
FCurrentMacroRegistry := TMacroRegistry.Create(nil);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TMacroExpander.Destroy;
|
||||||
|
begin
|
||||||
|
FCurrentMacroRegistry.Free;
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMacroExpander.EnterMacroScope;
|
||||||
|
begin
|
||||||
|
// Erstellt eine neue Registry mit der aktuellen als Parent
|
||||||
|
FCurrentMacroRegistry := TMacroRegistry.Create(FCurrentMacroRegistry);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMacroExpander.ExitMacroScope;
|
||||||
|
var
|
||||||
|
oldRegistry: TMacroRegistry;
|
||||||
|
begin
|
||||||
|
oldRegistry := FCurrentMacroRegistry;
|
||||||
|
FCurrentMacroRegistry := oldRegistry.FParent;
|
||||||
|
oldRegistry.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TMacroExpander.ExpandMacros(
|
class function TMacroExpander.ExpandMacros(
|
||||||
const InitialScope: IExecutionScope;
|
const InitialScope: IExecutionScope;
|
||||||
const RootNode: IAstNode;
|
const RootNode: IAstNode;
|
||||||
out Descriptor: IScopeDescriptor;
|
|
||||||
const EvaluatorFactory: TEvaluatorFactory
|
const EvaluatorFactory: TEvaluatorFactory
|
||||||
): IAstNode;
|
): IAstNode;
|
||||||
begin
|
begin
|
||||||
|
// IAstMacroExpander.Execute gibt keinen Descriptor mehr zurück
|
||||||
var expander := TMacroExpander.Create(InitialScope, EvaluatorFactory) as IAstMacroExpander;
|
var expander := TMacroExpander.Create(InitialScope, EvaluatorFactory) as IAstMacroExpander;
|
||||||
Result := expander.Execute(RootNode, Descriptor);
|
Result := expander.Execute(RootNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMacroExpander.Execute(const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
|
function TMacroExpander.Execute(const RootNode: IAstNode): IAstNode;
|
||||||
begin
|
begin
|
||||||
// This executes the transformation (Accept)
|
// This executes the transformation (Accept)
|
||||||
Result := Accept(RootNode); // Calls the IAstNode-returning helper
|
Result := Accept(RootNode); // Calls the IAstNode-returning helper
|
||||||
@@ -255,13 +335,35 @@ begin
|
|||||||
if not Assigned(Result) then
|
if not Assigned(Result) then
|
||||||
Result := TAst.Block([]); // e.g. if root was (defmacro ...)
|
Result := TAst.Block([]); // e.g. if root was (defmacro ...)
|
||||||
|
|
||||||
Descriptor := FCurrentDescriptor;
|
// Descriptor := FCurrentDescriptor; // Entfernt
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMacroExpander.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
|
||||||
|
begin
|
||||||
|
// Ein 'do'-Block eröffnet einen neuen Scope für Makros
|
||||||
|
EnterMacroScope;
|
||||||
|
try
|
||||||
|
Result := inherited VisitBlockExpression(Node);
|
||||||
|
finally
|
||||||
|
ExitMacroScope;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMacroExpander.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||||
|
begin
|
||||||
|
// Eine 'fn' eröffnet einen neuen Scope für Makros
|
||||||
|
EnterMacroScope;
|
||||||
|
try
|
||||||
|
Result := inherited VisitLambdaExpression(Node);
|
||||||
|
finally
|
||||||
|
ExitMacroScope;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMacroExpander.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode;
|
function TMacroExpander.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode;
|
||||||
begin
|
begin
|
||||||
// Register the macro in the current descriptor
|
// Register the macro in the *current* macro registry
|
||||||
FCurrentDescriptor.DefineMacro(Node.Name.Name, Node);
|
FCurrentMacroRegistry.Define(Node.Name.Name, Node);
|
||||||
|
|
||||||
// Keep the node in the AST (for the visualizer).
|
// Keep the node in the AST (for the visualizer).
|
||||||
Result := Node;
|
Result := Node;
|
||||||
@@ -279,8 +381,8 @@ begin
|
|||||||
|
|
||||||
calleeIdentifier := Node.Callee.AsIdentifier;
|
calleeIdentifier := Node.Callee.AsIdentifier;
|
||||||
|
|
||||||
// Check if this identifier is a macro
|
// Check if this identifier is a macro in the current registry
|
||||||
macroDef := FCurrentDescriptor.FindMacro(calleeIdentifier.Name);
|
macroDef := FCurrentMacroRegistry.Find(calleeIdentifier.Name);
|
||||||
if macroDef = nil then
|
if macroDef = nil then
|
||||||
exit(inherited VisitFunctionCall(Node)); // Not a macro, let transformer continue
|
exit(inherited VisitFunctionCall(Node)); // Not a macro, let transformer continue
|
||||||
|
|
||||||
@@ -309,7 +411,7 @@ begin
|
|||||||
boundSubAst: IAstNode;
|
boundSubAst: IAstNode;
|
||||||
begin
|
begin
|
||||||
// This is the compile-time evaluation (Binder + Evaluator)
|
// This is the compile-time evaluation (Binder + Evaluator)
|
||||||
// [FIX] It must run in the 'expansionScope' which contains the parameters.
|
// Es wird der 'expansionScope' verwendet, der die AST-Argumente enthält
|
||||||
boundSubAst := TAstBinder.Bind(expansionScope, ANodeToEvaluate, subDescriptor);
|
boundSubAst := TAstBinder.Bind(expansionScope, ANodeToEvaluate, subDescriptor);
|
||||||
|
|
||||||
// Create eval scope from the new descriptor, parented to the expansion scope
|
// Create eval scope from the new descriptor, parented to the expansion scope
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ uses
|
|||||||
Myc.Data.Scalar,
|
Myc.Data.Scalar,
|
||||||
Myc.Data.Value,
|
Myc.Data.Value,
|
||||||
Myc.Data.Keyword,
|
Myc.Data.Keyword,
|
||||||
|
Myc.Ast.Scope,
|
||||||
Myc.Ast.Types;
|
Myc.Ast.Types;
|
||||||
|
|
||||||
type
|
type
|
||||||
@@ -78,19 +79,6 @@ type
|
|||||||
|
|
||||||
// --- Concrete Type Definitions ---
|
// --- Concrete Type Definitions ---
|
||||||
|
|
||||||
// Defines how an identifier's address was resolved.
|
|
||||||
TAddressKind = (akUnresolved, akLocalOrParent, akUpvalue);
|
|
||||||
|
|
||||||
TResolvedAddress = record
|
|
||||||
Kind: TAddressKind;
|
|
||||||
ScopeDepth: Integer;
|
|
||||||
SlotIndex: Integer;
|
|
||||||
constructor Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer);
|
|
||||||
class operator Initialize(out Dest: TResolvedAddress);
|
|
||||||
public
|
|
||||||
class operator Equal(const A: TResolvedAddress; B: TResolvedAddress): Boolean;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// A single field in a record literal
|
// A single field in a record literal
|
||||||
TRecordFieldLiteral = record
|
TRecordFieldLiteral = record
|
||||||
Key: IKeywordNode;
|
Key: IKeywordNode;
|
||||||
@@ -397,6 +385,9 @@ type
|
|||||||
function Execute(const RootNode: IAstNode): TDataValue;
|
function Execute(const RootNode: IAstNode): TDataValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// A factory for creating visitors, primarily used by the debugger subsystem.
|
||||||
|
TEvaluatorFactory = reference to function(const Scope: IExecutionScope): IEvaluatorVisitor;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@@ -413,27 +404,6 @@ begin
|
|||||||
Result := Result.Substring(2);
|
Result := Result.Substring(2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TResolvedAddress }
|
|
||||||
|
|
||||||
constructor TResolvedAddress.Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer);
|
|
||||||
begin
|
|
||||||
Kind := AKind;
|
|
||||||
ScopeDepth := AScopeDepth;
|
|
||||||
SlotIndex := ASlotIndex;
|
|
||||||
end;
|
|
||||||
|
|
||||||
class operator TResolvedAddress.Equal(const A: TResolvedAddress; B: TResolvedAddress): Boolean;
|
|
||||||
begin
|
|
||||||
Result := (A.Kind = B.Kind) and (A.ScopeDepth = B.ScopeDepth) and (A.SlotIndex = B.SlotIndex);
|
|
||||||
end;
|
|
||||||
|
|
||||||
class operator TResolvedAddress.Initialize(out Dest: TResolvedAddress);
|
|
||||||
begin
|
|
||||||
Dest.Kind := akUnresolved;
|
|
||||||
Dest.ScopeDepth := -1;
|
|
||||||
Dest.SlotIndex := -1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TRecordFieldLiteral }
|
{ TRecordFieldLiteral }
|
||||||
|
|
||||||
constructor TRecordFieldLiteral.Create(const AKey: IKeywordNode; const AValue: IAstNode);
|
constructor TRecordFieldLiteral.Create(const AKey: IKeywordNode; const AValue: IAstNode);
|
||||||
|
|||||||
+43
-45
@@ -7,13 +7,25 @@ uses
|
|||||||
System.Generics.Collections,
|
System.Generics.Collections,
|
||||||
System.Classes,
|
System.Classes,
|
||||||
Myc.Data.Value,
|
Myc.Data.Value,
|
||||||
Myc.Ast.Nodes,
|
|
||||||
Myc.Ast.Types;
|
Myc.Ast.Types;
|
||||||
|
|
||||||
type
|
type
|
||||||
IExecutionScope = interface;
|
IExecutionScope = interface;
|
||||||
IScopeDescriptor = interface;
|
IScopeDescriptor = interface;
|
||||||
|
|
||||||
|
// Defines how an identifier's address was resolved.
|
||||||
|
TAddressKind = (akUnresolved, akLocalOrParent, akUpvalue);
|
||||||
|
|
||||||
|
TResolvedAddress = record
|
||||||
|
Kind: TAddressKind;
|
||||||
|
ScopeDepth: Integer;
|
||||||
|
SlotIndex: Integer;
|
||||||
|
constructor Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer);
|
||||||
|
class operator Initialize(out Dest: TResolvedAddress);
|
||||||
|
public
|
||||||
|
class operator Equal(const A: TResolvedAddress; B: TResolvedAddress): Boolean;
|
||||||
|
end;
|
||||||
|
|
||||||
// A resolved symbol, containing its runtime address and static type.
|
// A resolved symbol, containing its runtime address and static type.
|
||||||
TResolvedSymbol = record
|
TResolvedSymbol = record
|
||||||
Address: TResolvedAddress;
|
Address: TResolvedAddress;
|
||||||
@@ -68,18 +80,15 @@ type
|
|||||||
function Define(const Name: string; const AType: IStaticType = nil): Integer;
|
function Define(const Name: string; const AType: IStaticType = nil): Integer;
|
||||||
// Updates the type of an already defined symbol (e.g., for lambda self-reference).
|
// Updates the type of an already defined symbol (e.g., for lambda self-reference).
|
||||||
procedure UpdateType(SlotIndex: Integer; const AType: IStaticType);
|
procedure UpdateType(SlotIndex: Integer; const AType: IStaticType);
|
||||||
procedure DefineMacro(const Name: string; const Node: IMacroDefinitionNode);
|
|
||||||
// Finds a symbol, returns its address and type.
|
// Finds a symbol, returns its address and type.
|
||||||
function FindSymbol(const Name: string): TResolvedSymbol;
|
function FindSymbol(const Name: string): TResolvedSymbol;
|
||||||
function FindMacro(const Name: string): IMacroDefinitionNode;
|
|
||||||
property Parent: IScopeDescriptor read GetParent;
|
property Parent: IScopeDescriptor read GetParent;
|
||||||
property SlotCount: Integer read GetSlotCount;
|
property SlotCount: Integer read GetSlotCount;
|
||||||
property Symbols: TDictionary<string, Integer> read GetSymbols;
|
property Symbols: TDictionary<string, Integer> read GetSymbols;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// A factory for creating visitors, primarily used by the debugger subsystem.
|
|
||||||
TEvaluatorFactory = reference to function(const Scope: IExecutionScope): IEvaluatorVisitor;
|
|
||||||
|
|
||||||
TScope = record
|
TScope = record
|
||||||
class function CreateScope(
|
class function CreateScope(
|
||||||
const Parent: IExecutionScope;
|
const Parent: IExecutionScope;
|
||||||
@@ -93,8 +102,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
System.Generics.Defaults,
|
System.Generics.Defaults,
|
||||||
System.SyncObjs,
|
System.SyncObjs;
|
||||||
Myc.Ast;
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TExecutionScope = class(TInterfacedObject, IExecutionScope)
|
TExecutionScope = class(TInterfacedObject, IExecutionScope)
|
||||||
@@ -151,7 +159,7 @@ type
|
|||||||
private
|
private
|
||||||
FParent: IScopeDescriptor;
|
FParent: IScopeDescriptor;
|
||||||
FSymbols: TDictionary<string, Integer>;
|
FSymbols: TDictionary<string, Integer>;
|
||||||
FMacros: TDictionary<string, IMacroDefinitionNode>;
|
// FMacros: TDictionary<string, IMacroDefinitionNode>; // Entfernt
|
||||||
FSlotTypes: TArray<IStaticType>; // Stores types by SlotIndex
|
FSlotTypes: TArray<IStaticType>; // Stores types by SlotIndex
|
||||||
function GetParent: IScopeDescriptor;
|
function GetParent: IScopeDescriptor;
|
||||||
function GetSlotCount: Integer;
|
function GetSlotCount: Integer;
|
||||||
@@ -163,14 +171,35 @@ type
|
|||||||
class function CreateDescriptor(const Scope: IExecutionScope): IScopeDescriptor; static;
|
class function CreateDescriptor(const Scope: IExecutionScope): IScopeDescriptor; static;
|
||||||
function Define(const Name: string; const AType: IStaticType): Integer;
|
function Define(const Name: string; const AType: IStaticType): Integer;
|
||||||
procedure UpdateType(SlotIndex: Integer; const AType: IStaticType = nil);
|
procedure UpdateType(SlotIndex: Integer; const AType: IStaticType = nil);
|
||||||
procedure DefineMacro(const Name: string; const Node: IMacroDefinitionNode);
|
// procedure DefineMacro(const Name: string; const Node: IMacroDefinitionNode); // Entfernt
|
||||||
function FindSymbol(const Name: string): TResolvedSymbol;
|
function FindSymbol(const Name: string): TResolvedSymbol;
|
||||||
function FindMacro(const Name: string): IMacroDefinitionNode;
|
// function FindMacro(const Name: string): IMacroDefinitionNode; // Entfernt
|
||||||
function CreateScope(const Parent: IExecutionScope): IExecutionScope;
|
function CreateScope(const Parent: IExecutionScope): IExecutionScope;
|
||||||
procedure PopulateFromScope(Scope: TExecutionScope);
|
procedure PopulateFromScope(Scope: TExecutionScope);
|
||||||
property Symbols: TDictionary<string, Integer> read FSymbols;
|
property Symbols: TDictionary<string, Integer> read FSymbols;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TResolvedAddress }
|
||||||
|
|
||||||
|
constructor TResolvedAddress.Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer);
|
||||||
|
begin
|
||||||
|
Kind := AKind;
|
||||||
|
ScopeDepth := AScopeDepth;
|
||||||
|
SlotIndex := ASlotIndex;
|
||||||
|
end;
|
||||||
|
|
||||||
|
class operator TResolvedAddress.Equal(const A: TResolvedAddress; B: TResolvedAddress): Boolean;
|
||||||
|
begin
|
||||||
|
Result := (A.Kind = B.Kind) and (A.ScopeDepth = B.ScopeDepth) and (A.SlotIndex = B.SlotIndex);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class operator TResolvedAddress.Initialize(out Dest: TResolvedAddress);
|
||||||
|
begin
|
||||||
|
Dest.Kind := akUnresolved;
|
||||||
|
Dest.ScopeDepth := -1;
|
||||||
|
Dest.SlotIndex := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TResolvedSymbol }
|
{ TResolvedSymbol }
|
||||||
|
|
||||||
constructor TResolvedSymbol.Create(const AAddress: TResolvedAddress; const AStaticType: IStaticType);
|
constructor TResolvedSymbol.Create(const AAddress: TResolvedAddress; const AStaticType: IStaticType);
|
||||||
@@ -499,14 +528,14 @@ begin
|
|||||||
inherited Create;
|
inherited Create;
|
||||||
FParent := AParent;
|
FParent := AParent;
|
||||||
FSymbols := TDictionary<string, Integer>.Create;
|
FSymbols := TDictionary<string, Integer>.Create;
|
||||||
FMacros := TDictionary<string, IMacroDefinitionNode>.Create;
|
// FMacros := TDictionary<string, IMacroDefinitionNode>.Create; // Entfernt
|
||||||
FSlotTypes := [];
|
FSlotTypes := [];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TScopeDescriptor.Destroy;
|
destructor TScopeDescriptor.Destroy;
|
||||||
begin
|
begin
|
||||||
FSlotTypes := nil;
|
FSlotTypes := nil;
|
||||||
FMacros.Free;
|
// FMacros.Free; // Entfernt
|
||||||
FSymbols.Free;
|
FSymbols.Free;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
@@ -547,26 +576,6 @@ begin
|
|||||||
else TTypes.Unknown;
|
else TTypes.Unknown;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TScopeDescriptor.DefineMacro(const Name: string; const Node: IMacroDefinitionNode);
|
|
||||||
begin
|
|
||||||
FMacros.AddOrSetValue(Name, Node);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TScopeDescriptor.FindMacro(const Name: string): IMacroDefinitionNode;
|
|
||||||
var
|
|
||||||
currentDescriptor: TScopeDescriptor;
|
|
||||||
begin
|
|
||||||
// Find a macro by searching up the parent scope chain.
|
|
||||||
Result := nil;
|
|
||||||
currentDescriptor := Self;
|
|
||||||
while Assigned(currentDescriptor) do
|
|
||||||
begin
|
|
||||||
if currentDescriptor.FMacros.TryGetValue(Name, Result) then
|
|
||||||
exit;
|
|
||||||
currentDescriptor := currentDescriptor.FParent as TScopeDescriptor;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TScopeDescriptor.FindSymbol(const Name: string): TResolvedSymbol;
|
function TScopeDescriptor.FindSymbol(const Name: string): TResolvedSymbol;
|
||||||
var
|
var
|
||||||
currentDescriptor: IScopeDescriptor;
|
currentDescriptor: IScopeDescriptor;
|
||||||
@@ -633,18 +642,7 @@ begin
|
|||||||
// We cannot recover the static type from the runtime scope.
|
// We cannot recover the static type from the runtime scope.
|
||||||
// FSlotTypes[slotIndex] remains TTypes.Unknown.
|
// FSlotTypes[slotIndex] remains TTypes.Unknown.
|
||||||
|
|
||||||
// Check if the symbol is also a macro and add it to the macro table.
|
// Makro-Logik hier entfernt
|
||||||
|
|
||||||
var val := Scope.ValuesArray[slotIndex].GetContent;
|
|
||||||
if val.Kind = vkInterface then
|
|
||||||
begin
|
|
||||||
var node := val.AsIntf<IAstNode>;
|
|
||||||
if (node <> nil) and (node.Kind = akMacroDefinition) then
|
|
||||||
begin
|
|
||||||
if not FMacros.ContainsKey(name) then
|
|
||||||
FMacros.Add(name, node.AsMacroDefinition);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user