Generic Visitors
This commit is contained in:
@@ -23,9 +23,6 @@ type
|
|||||||
FScope: IExecutionScope;
|
FScope: IExecutionScope;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
// Setup the registry-based handlers
|
|
||||||
procedure SetupHandlers; override;
|
|
||||||
|
|
||||||
// --- Core Logic Implementation (Legacy Virtual Overrides) ---
|
// --- Core Logic Implementation (Legacy Virtual Overrides) ---
|
||||||
// These are kept as virtual methods so TDebugEvaluatorVisitor can still override them.
|
// These are kept as virtual methods so TDebugEvaluatorVisitor can still override them.
|
||||||
function VisitConstant(const Node: IConstantNode): TDataValue; override;
|
function VisitConstant(const Node: IConstantNode): TDataValue; override;
|
||||||
@@ -117,17 +114,6 @@ begin
|
|||||||
Assert(Assigned(AScope));
|
Assert(Assigned(AScope));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TEvaluatorVisitor.SetupHandlers;
|
|
||||||
begin
|
|
||||||
// The base SetupHandlers registers delegates that call the virtual methods (VisitConstant, etc.).
|
|
||||||
// Since TEvaluatorVisitor still implements its logic by overriding these virtual methods (for now),
|
|
||||||
// we just call inherited.
|
|
||||||
//
|
|
||||||
// In Phase 2/3 of refactoring, we would move the logic from VisitConstant directly into
|
|
||||||
// anonymous methods or separate handler functions registered here, bypassing the virtual table.
|
|
||||||
inherited;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TEvaluatorVisitor.Execute(const RootNode: IAstNode): TDataValue;
|
function TEvaluatorVisitor.Execute(const RootNode: IAstNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
if not Assigned(RootNode) then
|
if not Assigned(RootNode) then
|
||||||
|
|||||||
@@ -513,7 +513,6 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
IAstVisitor = interface
|
IAstVisitor = interface
|
||||||
// --- Central Dispatch Method (New) ---
|
|
||||||
function Visit(const Node: IAstNode): TDataValue;
|
function Visit(const Node: IAstNode): TDataValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
+49
-46
@@ -16,6 +16,7 @@ type
|
|||||||
|
|
||||||
// Delegate for handling a specific node kind within the visitor context
|
// Delegate for handling a specific node kind within the visitor context
|
||||||
TNodeHandler<T> = reference to function(const Node: IAstNode): T;
|
TNodeHandler<T> = reference to function(const Node: IAstNode): T;
|
||||||
|
TRegisterHandler<T> = reference to procedure(Kind: TAstNodeKind; const Handler: TNodeHandler<T>);
|
||||||
|
|
||||||
TAstVisitor<T> = class abstract(TInterfacedObject, IAstVisitor)
|
TAstVisitor<T> = class abstract(TInterfacedObject, IAstVisitor)
|
||||||
strict private
|
strict private
|
||||||
@@ -29,13 +30,9 @@ type
|
|||||||
function VisitBridge(const Node: IAstNode): TDataValue;
|
function VisitBridge(const Node: IAstNode): TDataValue;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
// Registers a handler for a specific node kind.
|
|
||||||
// Subclasses can call this in their constructor/SetupHandlers to override behavior without implementing VisitXYZ.
|
|
||||||
procedure RegisterHandler(Kind: TAstNodeKind; Handler: TNodeHandler<T>);
|
|
||||||
|
|
||||||
// Initial setup of the dispatch table.
|
// Initial setup of the dispatch table.
|
||||||
// The base implementation maps all kinds to the legacy VisitXYZ virtual methods.
|
// The base implementation maps all kinds to the legacy VisitXYZ virtual methods.
|
||||||
procedure SetupHandlers; virtual;
|
procedure SetupHandlers(const Register: TRegisterHandler<T>); virtual;
|
||||||
|
|
||||||
// The central dispatch method. Looks up the handler in the registry.
|
// The central dispatch method. Looks up the handler in the registry.
|
||||||
function Visit(const Node: IAstNode): T; virtual;
|
function Visit(const Node: IAstNode): T; virtual;
|
||||||
@@ -84,7 +81,8 @@ type
|
|||||||
function Accept(const Node: IAstNode): T; virtual;
|
function Accept(const Node: IAstNode): T; virtual;
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create;
|
procedure AfterConstruction; override;
|
||||||
|
procedure BeforeDestruction; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Helper for transformation visitors (returns IAstNode)
|
// Helper for transformation visitors (returns IAstNode)
|
||||||
@@ -137,74 +135,79 @@ implementation
|
|||||||
|
|
||||||
{ TAstVisitor<T> }
|
{ TAstVisitor<T> }
|
||||||
|
|
||||||
constructor TAstVisitor<T>.Create;
|
procedure TAstVisitor<T>.AfterConstruction;
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited;
|
||||||
SetupHandlers;
|
SetupHandlers(procedure(Kind: TAstNodeKind; const Handler: TNodeHandler<T>) begin FHandlers[Kind] := Handler; end);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor<T>.RegisterHandler(Kind: TAstNodeKind; Handler: TNodeHandler<T>);
|
procedure TAstVisitor<T>.BeforeDestruction;
|
||||||
begin
|
begin
|
||||||
FHandlers[Kind] := Handler;
|
for var i := Low(TAstNodeKind) to High(TAstNodeKind) do
|
||||||
|
FHandlers[i] := nil;
|
||||||
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor<T>.SetupHandlers;
|
procedure TAstVisitor<T>.SetupHandlers(const Register: TRegisterHandler<T>);
|
||||||
begin
|
begin
|
||||||
// Map all kinds to the legacy virtual methods.
|
// Map all kinds to the legacy virtual methods.
|
||||||
// This provides the compatibility layer for existing subclasses.
|
// This provides the compatibility layer for existing subclasses.
|
||||||
// In Phase 2, subclasses will register their own handlers directly here.
|
// In Phase 2, subclasses will register their own handlers directly here.
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
FHandlers[akConstant] := function(const Node: IAstNode): T begin Result := VisitConstant(Node.AsConstant); end;
|
Register(akConstant, function(const Node: IAstNode): T begin Result := VisitConstant(Node.AsConstant); end);
|
||||||
FHandlers[akIdentifier] := function(const Node: IAstNode): T begin Result := VisitIdentifier(Node.AsIdentifier); end;
|
Register(akIdentifier, function(const Node: IAstNode): T begin Result := VisitIdentifier(Node.AsIdentifier); end);
|
||||||
FHandlers[akKeyword] := function(const Node: IAstNode): T begin Result := VisitKeyword(Node.AsKeyword); end;
|
Register(akKeyword, function(const Node: IAstNode): T begin Result := VisitKeyword(Node.AsKeyword); end);
|
||||||
|
|
||||||
// Lists
|
// Lists
|
||||||
FHandlers[akParameterList] := function(const Node: IAstNode): T begin Result := VisitParameterList(Node.AsParameterList); end;
|
Register(akParameterList, function(const Node: IAstNode): T begin Result := VisitParameterList(Node.AsParameterList); end);
|
||||||
FHandlers[akArgumentList] := function(const Node: IAstNode): T begin Result := VisitArgumentList(Node.AsArgumentList); end;
|
Register(akArgumentList, function(const Node: IAstNode): T begin Result := VisitArgumentList(Node.AsArgumentList); end);
|
||||||
FHandlers[akExpressionList] := function(const Node: IAstNode): T begin Result := VisitExpressionList(Node.AsExpressionList); end;
|
Register(akExpressionList, function(const Node: IAstNode): T begin Result := VisitExpressionList(Node.AsExpressionList); end);
|
||||||
FHandlers[akRecordFieldList] := function(const Node: IAstNode): T begin Result := VisitRecordFieldList(Node.AsRecordFieldList); end;
|
Register(akRecordFieldList, function(const Node: IAstNode): T begin Result := VisitRecordFieldList(Node.AsRecordFieldList); end);
|
||||||
FHandlers[akRecordField] := function(const Node: IAstNode): T begin Result := VisitRecordField(Node.AsRecordField); end;
|
Register(akRecordField, function(const Node: IAstNode): T begin Result := VisitRecordField(Node.AsRecordField); end);
|
||||||
|
|
||||||
// Structural
|
// Structural
|
||||||
FHandlers[akIfExpression] := function(const Node: IAstNode): T begin Result := VisitIfExpression(Node.AsIfExpression); end;
|
Register(akIfExpression, function(const Node: IAstNode): T begin Result := VisitIfExpression(Node.AsIfExpression); end);
|
||||||
FHandlers[akCondExpression] := function(const Node: IAstNode): T begin Result := VisitCondExpression(Node.AsCondExpression); end;
|
Register(akCondExpression, function(const Node: IAstNode): T begin Result := VisitCondExpression(Node.AsCondExpression); end);
|
||||||
FHandlers[akLambdaExpression] := function(const Node: IAstNode): T begin Result := VisitLambdaExpression(Node.AsLambdaExpression); end;
|
Register(akLambdaExpression, function(const Node: IAstNode): T begin Result := VisitLambdaExpression(Node.AsLambdaExpression); end);
|
||||||
FHandlers[akFunctionCall] := function(const Node: IAstNode): T begin Result := VisitFunctionCall(Node.AsFunctionCall); end;
|
Register(akFunctionCall, function(const Node: IAstNode): T begin Result := VisitFunctionCall(Node.AsFunctionCall); end);
|
||||||
FHandlers[akMacroExpansion] := function(const Node: IAstNode): T begin Result := VisitMacroExpansionNode(Node.AsMacroExpansion); end;
|
Register(akMacroExpansion, function(const Node: IAstNode): T begin Result := VisitMacroExpansionNode(Node.AsMacroExpansion); end);
|
||||||
FHandlers[akBlockExpression] := function(const Node: IAstNode): T begin Result := VisitBlockExpression(Node.AsBlockExpression); end;
|
Register(akBlockExpression, function(const Node: IAstNode): T begin Result := VisitBlockExpression(Node.AsBlockExpression); end);
|
||||||
FHandlers[akVariableDeclaration] :=
|
Register(
|
||||||
function(const Node: IAstNode): T begin Result := VisitVariableDeclaration(Node.AsVariableDeclaration); end;
|
akVariableDeclaration,
|
||||||
FHandlers[akAssignment] := function(const Node: IAstNode): T begin Result := VisitAssignment(Node.AsAssignment); end;
|
function(const Node: IAstNode): T begin Result := VisitVariableDeclaration(Node.AsVariableDeclaration); end
|
||||||
FHandlers[akMacroDefinition] := function(const Node: IAstNode): T begin Result := VisitMacroDefinition(Node.AsMacroDefinition); end;
|
);
|
||||||
FHandlers[akQuasiquote] := function(const Node: IAstNode): T begin Result := VisitQuasiquote(Node.AsQuasiquote); end;
|
Register(akAssignment, function(const Node: IAstNode): T begin Result := VisitAssignment(Node.AsAssignment); end);
|
||||||
FHandlers[akUnquote] := function(const Node: IAstNode): T begin Result := VisitUnquote(Node.AsUnquote); end;
|
Register(akMacroDefinition, function(const Node: IAstNode): T begin Result := VisitMacroDefinition(Node.AsMacroDefinition); end);
|
||||||
FHandlers[akUnquoteSplicing] := function(const Node: IAstNode): T begin Result := VisitUnquoteSplicing(Node.AsUnquoteSplicing); end;
|
Register(akQuasiquote, function(const Node: IAstNode): T begin Result := VisitQuasiquote(Node.AsQuasiquote); end);
|
||||||
FHandlers[akIndexer] := function(const Node: IAstNode): T begin Result := VisitIndexer(Node.AsIndexer); end;
|
Register(akUnquote, function(const Node: IAstNode): T begin Result := VisitUnquote(Node.AsUnquote); end);
|
||||||
FHandlers[akMemberAccess] := function(const Node: IAstNode): T begin Result := VisitMemberAccess(Node.AsMemberAccess); end;
|
Register(akUnquoteSplicing, function(const Node: IAstNode): T begin Result := VisitUnquoteSplicing(Node.AsUnquoteSplicing); end);
|
||||||
FHandlers[akRecordLiteral] := function(const Node: IAstNode): T begin Result := VisitRecordLiteral(Node.AsRecordLiteral); end;
|
Register(akIndexer, function(const Node: IAstNode): T begin Result := VisitIndexer(Node.AsIndexer); end);
|
||||||
FHandlers[akCreateSeries] := function(const Node: IAstNode): T begin Result := VisitCreateSeries(Node.AsCreateSeries); end;
|
Register(akMemberAccess, function(const Node: IAstNode): T begin Result := VisitMemberAccess(Node.AsMemberAccess); end);
|
||||||
FHandlers[akAddSeriesItem] := function(const Node: IAstNode): T begin Result := VisitAddSeriesItem(Node.AsAddSeriesItem); end;
|
Register(akRecordLiteral, function(const Node: IAstNode): T begin Result := VisitRecordLiteral(Node.AsRecordLiteral); end);
|
||||||
FHandlers[akSeriesLength] := function(const Node: IAstNode): T begin Result := VisitSeriesLength(Node.AsSeriesLength); end;
|
Register(akCreateSeries, function(const Node: IAstNode): T begin Result := VisitCreateSeries(Node.AsCreateSeries); end);
|
||||||
FHandlers[akRecur] := function(const Node: IAstNode): T begin Result := VisitRecurNode(Node.AsRecur); end;
|
Register(akAddSeriesItem, function(const Node: IAstNode): T begin Result := VisitAddSeriesItem(Node.AsAddSeriesItem); end);
|
||||||
FHandlers[akNop] := function(const Node: IAstNode): T begin Result := VisitNop(Node.AsNop); end;
|
Register(akSeriesLength, function(const Node: IAstNode): T begin Result := VisitSeriesLength(Node.AsSeriesLength); end);
|
||||||
|
Register(akRecur, function(const Node: IAstNode): T begin Result := VisitRecurNode(Node.AsRecur); end);
|
||||||
|
Register(akNop, function(const Node: IAstNode): T begin Result := VisitNop(Node.AsNop); end);
|
||||||
|
|
||||||
// Pipes
|
// Pipes
|
||||||
FHandlers[akPipeInput] := function(const Node: IAstNode): T begin Result := VisitPipeInput(Node.AsPipeInput); end;
|
Register(akPipeInput, function(const Node: IAstNode): T begin Result := VisitPipeInput(Node.AsPipeInput); end);
|
||||||
FHandlers[akPipeSelectorList] := function(const Node: IAstNode): T begin Result := VisitPipeSelectorList(Node.AsPipeSelectorList); end;
|
Register(akPipeSelectorList, function(const Node: IAstNode): T begin Result := VisitPipeSelectorList(Node.AsPipeSelectorList); end);
|
||||||
FHandlers[akPipeInputList] := function(const Node: IAstNode): T begin Result := VisitPipeInputList(Node.AsPipeInputList); end;
|
Register(akPipeInputList, function(const Node: IAstNode): T begin Result := VisitPipeInputList(Node.AsPipeInputList); end);
|
||||||
FHandlers[akPipe] := function(const Node: IAstNode): T begin Result := VisitPipe(Node.AsPipe); end;
|
Register(akPipe, function(const Node: IAstNode): T begin Result := VisitPipe(Node.AsPipe); end);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.Visit(const Node: IAstNode): T;
|
function TAstVisitor<T>.Visit(const Node: IAstNode): T;
|
||||||
var
|
var
|
||||||
|
[unsafe]
|
||||||
handler: TNodeHandler<T>;
|
handler: TNodeHandler<T>;
|
||||||
begin
|
begin
|
||||||
if not Assigned(Node) then
|
if not Assigned(Node) then
|
||||||
Exit(Default(T));
|
Exit(Default(T));
|
||||||
|
|
||||||
// O(1) Lookup
|
// O(1) Lookup
|
||||||
handler := FHandlers[Node.Kind];
|
handler := TNodeHandler<T>(FHandlers[Node.Kind]);
|
||||||
|
|
||||||
if Assigned(handler) then
|
if Assigned(handler) then
|
||||||
Result := handler(Node)
|
Result := handler(Node)
|
||||||
|
|||||||
Reference in New Issue
Block a user