diff --git a/Src/AST/Myc.Ast.Visitor.pas b/Src/AST/Myc.Ast.Visitor.pas index 816802b..4598b66 100644 --- a/Src/AST/Myc.Ast.Visitor.pas +++ b/Src/AST/Myc.Ast.Visitor.pas @@ -14,8 +14,11 @@ uses type TAstVisitor = class; - // Delegate for handling a specific node kind within the visitor context - TNodeHandler = reference to function(const Node: IAstNode): T; + // Delegate for handling a specific node kind within the visitor context. + // Receives the visitor instance explicitly to allow for stateless handlers or external logic. + TNodeHandler = reference to function(const Visitor: TAstVisitor; const Node: IAstNode): T; + + // Callback to register a handler for a specific node kind. TRegisterHandler = reference to procedure(Kind: TAstNodeKind; const Handler: TNodeHandler); TAstVisitor = class abstract(TInterfacedObject, IAstVisitor) @@ -138,6 +141,8 @@ implementation procedure TAstVisitor.AfterConstruction; begin inherited; + // We pass explicit anonymous methods that use the 'Visitor' argument. + // This ensures that even if handlers are moved out of context later, they operate on the passed visitor instance. SetupHandlers(procedure(Kind: TAstNodeKind; const Handler: TNodeHandler) begin FHandlers[Kind] := Handler; end); end; @@ -150,52 +155,110 @@ end; procedure TAstVisitor.SetupHandlers(const Register: TRegisterHandler); begin - // Map all kinds to the legacy virtual methods. - // This provides the compatibility layer for existing subclasses. - // In Phase 2, subclasses will register their own handlers directly here. + // Map all kinds to the legacy virtual methods using the passed Visitor instance (V). // Core - Register(akConstant, function(const Node: IAstNode): T begin Result := VisitConstant(Node.AsConstant); end); - Register(akIdentifier, function(const Node: IAstNode): T begin Result := VisitIdentifier(Node.AsIdentifier); end); - Register(akKeyword, function(const Node: IAstNode): T begin Result := VisitKeyword(Node.AsKeyword); end); + Register(akConstant, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitConstant(N.AsConstant); end); + Register(akIdentifier, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitIdentifier(N.AsIdentifier); end); + Register(akKeyword, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitKeyword(N.AsKeyword); end); // Lists - Register(akParameterList, function(const Node: IAstNode): T begin Result := VisitParameterList(Node.AsParameterList); end); - Register(akArgumentList, function(const Node: IAstNode): T begin Result := VisitArgumentList(Node.AsArgumentList); end); - Register(akExpressionList, function(const Node: IAstNode): T begin Result := VisitExpressionList(Node.AsExpressionList); end); - Register(akRecordFieldList, function(const Node: IAstNode): T begin Result := VisitRecordFieldList(Node.AsRecordFieldList); end); - Register(akRecordField, function(const Node: IAstNode): T begin Result := VisitRecordField(Node.AsRecordField); end); + Register( + akParameterList, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitParameterList(N.AsParameterList); end + ); + Register( + akArgumentList, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitArgumentList(N.AsArgumentList); end + ); + Register( + akExpressionList, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitExpressionList(N.AsExpressionList); end + ); + Register( + akRecordFieldList, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitRecordFieldList(N.AsRecordFieldList); end + ); + Register( + akRecordField, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitRecordField(N.AsRecordField); end + ); // Structural - Register(akIfExpression, function(const Node: IAstNode): T begin Result := VisitIfExpression(Node.AsIfExpression); end); - Register(akCondExpression, function(const Node: IAstNode): T begin Result := VisitCondExpression(Node.AsCondExpression); end); - Register(akLambdaExpression, function(const Node: IAstNode): T begin Result := VisitLambdaExpression(Node.AsLambdaExpression); end); - Register(akFunctionCall, function(const Node: IAstNode): T begin Result := VisitFunctionCall(Node.AsFunctionCall); end); - Register(akMacroExpansion, function(const Node: IAstNode): T begin Result := VisitMacroExpansionNode(Node.AsMacroExpansion); end); - Register(akBlockExpression, function(const Node: IAstNode): T begin Result := VisitBlockExpression(Node.AsBlockExpression); end); + Register( + akIfExpression, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitIfExpression(N.AsIfExpression); end + ); + Register( + akCondExpression, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitCondExpression(N.AsCondExpression); end + ); + Register( + akLambdaExpression, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitLambdaExpression(N.AsLambdaExpression); end + ); + Register( + akFunctionCall, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitFunctionCall(N.AsFunctionCall); end + ); + Register( + akMacroExpansion, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitMacroExpansionNode(N.AsMacroExpansion); end + ); + Register( + akBlockExpression, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitBlockExpression(N.AsBlockExpression); end + ); Register( akVariableDeclaration, - function(const Node: IAstNode): T begin Result := VisitVariableDeclaration(Node.AsVariableDeclaration); end + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitVariableDeclaration(N.AsVariableDeclaration); end ); - Register(akAssignment, function(const Node: IAstNode): T begin Result := VisitAssignment(Node.AsAssignment); end); - Register(akMacroDefinition, function(const Node: IAstNode): T begin Result := VisitMacroDefinition(Node.AsMacroDefinition); end); - Register(akQuasiquote, function(const Node: IAstNode): T begin Result := VisitQuasiquote(Node.AsQuasiquote); end); - Register(akUnquote, function(const Node: IAstNode): T begin Result := VisitUnquote(Node.AsUnquote); end); - Register(akUnquoteSplicing, function(const Node: IAstNode): T begin Result := VisitUnquoteSplicing(Node.AsUnquoteSplicing); end); - Register(akIndexer, function(const Node: IAstNode): T begin Result := VisitIndexer(Node.AsIndexer); end); - Register(akMemberAccess, function(const Node: IAstNode): T begin Result := VisitMemberAccess(Node.AsMemberAccess); end); - Register(akRecordLiteral, function(const Node: IAstNode): T begin Result := VisitRecordLiteral(Node.AsRecordLiteral); end); - Register(akCreateSeries, function(const Node: IAstNode): T begin Result := VisitCreateSeries(Node.AsCreateSeries); end); - Register(akAddSeriesItem, function(const Node: IAstNode): T begin Result := VisitAddSeriesItem(Node.AsAddSeriesItem); 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); + Register(akAssignment, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitAssignment(N.AsAssignment); end); + Register( + akMacroDefinition, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitMacroDefinition(N.AsMacroDefinition); end + ); + Register(akQuasiquote, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitQuasiquote(N.AsQuasiquote); end); + Register(akUnquote, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitUnquote(N.AsUnquote); end); + Register( + akUnquoteSplicing, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitUnquoteSplicing(N.AsUnquoteSplicing); end + ); + Register(akIndexer, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitIndexer(N.AsIndexer); end); + Register( + akMemberAccess, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitMemberAccess(N.AsMemberAccess); end + ); + Register( + akRecordLiteral, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitRecordLiteral(N.AsRecordLiteral); end + ); + Register( + akCreateSeries, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitCreateSeries(N.AsCreateSeries); end + ); + Register( + akAddSeriesItem, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitAddSeriesItem(N.AsAddSeriesItem); end + ); + Register( + akSeriesLength, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitSeriesLength(N.AsSeriesLength); end + ); + Register(akRecur, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitRecurNode(N.AsRecur); end); + Register(akNop, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitNop(N.AsNop); end); // Pipes - Register(akPipeInput, function(const Node: IAstNode): T begin Result := VisitPipeInput(Node.AsPipeInput); end); - Register(akPipeSelectorList, function(const Node: IAstNode): T begin Result := VisitPipeSelectorList(Node.AsPipeSelectorList); end); - Register(akPipeInputList, function(const Node: IAstNode): T begin Result := VisitPipeInputList(Node.AsPipeInputList); end); - Register(akPipe, function(const Node: IAstNode): T begin Result := VisitPipe(Node.AsPipe); end); + Register(akPipeInput, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitPipeInput(N.AsPipeInput); end); + Register( + akPipeSelectorList, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitPipeSelectorList(N.AsPipeSelectorList); end + ); + Register( + akPipeInputList, + function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitPipeInputList(N.AsPipeInputList); end + ); + Register(akPipe, function(const V: TAstVisitor; const N: IAstNode): T begin Result := V.VisitPipe(N.AsPipe); end); end; function TAstVisitor.Visit(const Node: IAstNode): T; @@ -210,7 +273,7 @@ begin handler := TNodeHandler(FHandlers[Node.Kind]); if Assigned(handler) then - Result := handler(Node) + Result := handler(Self, Node) else raise ENoHandlerException.Create(Node.Kind.ToString); end;