Generic Visitors
This commit is contained in:
@@ -40,11 +40,16 @@ type
|
||||
FCurrentScope: TAnalysisScope;
|
||||
|
||||
procedure MarkDeclarationForBoxing(const AName: string);
|
||||
|
||||
strict private
|
||||
// Analysis Handlers (IAstNode signature)
|
||||
function VisitLambdaExpression(const Node: IAstNode): IAstNode;
|
||||
function VisitIdentifier(const Node: IAstNode): IAstNode;
|
||||
function VisitVariableDeclaration(const Node: IAstNode): IAstNode;
|
||||
|
||||
protected
|
||||
// Overridden Visit methods to perform analysis during traversal.
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; override;
|
||||
procedure SetupHandlers; override;
|
||||
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
@@ -126,6 +131,16 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TUpvalueAnalyzer.SetupHandlers;
|
||||
begin
|
||||
inherited SetupHandlers; // Load default transformer logic
|
||||
|
||||
// Override specific handlers for analysis
|
||||
Register(akLambdaExpression, VisitLambdaExpression);
|
||||
Register(akIdentifier, VisitIdentifier);
|
||||
Register(akVariableDeclaration, VisitVariableDeclaration);
|
||||
end;
|
||||
|
||||
function TUpvalueAnalyzer.Execute(const ARootNode: IAstNode): IAstNode;
|
||||
begin
|
||||
Result := Accept(ARootNode);
|
||||
@@ -167,32 +182,35 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TUpvalueAnalyzer.VisitIdentifier(const Node: IIdentifierNode): IAstNode;
|
||||
function TUpvalueAnalyzer.VisitIdentifier(const Node: IAstNode): IAstNode;
|
||||
begin
|
||||
// Check if this identifier refers to a variable from an outer scope
|
||||
MarkDeclarationForBoxing(Node.Name);
|
||||
MarkDeclarationForBoxing(Node.AsIdentifier.Name);
|
||||
|
||||
// Return original node (Analysis pass only)
|
||||
Result := Node;
|
||||
end;
|
||||
|
||||
function TUpvalueAnalyzer.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||
function TUpvalueAnalyzer.VisitLambdaExpression(const Node: IAstNode): IAstNode;
|
||||
var
|
||||
L: ILambdaExpressionNode;
|
||||
i: Integer;
|
||||
begin
|
||||
L := Node.AsLambdaExpression;
|
||||
|
||||
// 1. Enter new analysis scope
|
||||
FCurrentScope := TAnalysisScope.Create(FCurrentScope);
|
||||
try
|
||||
// 2. Register parameters (they mask outer variables)
|
||||
// We pass 'nil' as the node because we currently don't box parameters,
|
||||
// but we must ensure Resolve() finds them so we don't accidentally box a shadowed variable.
|
||||
for i := 0 to Node.Parameters.Count - 1 do
|
||||
for i := 0 to L.Parameters.Count - 1 do
|
||||
begin
|
||||
FCurrentScope.Define(Node.Parameters[i].Name, nil);
|
||||
FCurrentScope.Define(L.Parameters[i].Name, nil);
|
||||
end;
|
||||
|
||||
// 3. Visit Body
|
||||
Accept(Node.Body); // Recursive call
|
||||
Accept(L.Body); // Recursive call
|
||||
|
||||
// Rebuild if needed (default CoW behavior)
|
||||
Result := Node;
|
||||
@@ -204,15 +222,19 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TUpvalueAnalyzer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
|
||||
function TUpvalueAnalyzer.VisitVariableDeclaration(const Node: IAstNode): IAstNode;
|
||||
var
|
||||
V: IVariableDeclarationNode;
|
||||
begin
|
||||
V := Node.AsVariableDeclaration;
|
||||
|
||||
// 1. Visit initializer first (it executes in the CURRENT scope)
|
||||
if Assigned(Node.Initializer) then
|
||||
Accept(Node.Initializer);
|
||||
if Assigned(V.Initializer) then
|
||||
Accept(V.Initializer);
|
||||
|
||||
// 2. Define the variable in the CURRENT scope
|
||||
// Store the Node reference so we can add it to FBoxedDeclarations if captured.
|
||||
FCurrentScope.Define(Node.Target.AsIdentifier.Name, Node);
|
||||
FCurrentScope.Define(V.Target.AsIdentifier.Name, V);
|
||||
|
||||
Result := Node;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user