diff --git a/Src/AST/Myc.Ast.Compiler.Macros.pas b/Src/AST/Myc.Ast.Compiler.Macros.pas index 1731be8..bf1229f 100644 --- a/Src/AST/Myc.Ast.Compiler.Macros.pas +++ b/Src/AST/Myc.Ast.Compiler.Macros.pas @@ -26,10 +26,8 @@ type // Handles the expansion of the macro body template (Quasiquotes/Unquotes). TExpansionVisitor = class(TAstTransformer) - type - TEvaluateProc = reference to function(const Node: IAstNode): TDataValue; private - FEvaluate: TEvaluateProc; + FMacroEvaluator: TMacroEvaluatorProc; FMacroScope: IExecutionScope; FRenameMap: TDictionary; class var @@ -48,10 +46,14 @@ type function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override; function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override; public - constructor Create(const AMacroScope: IExecutionScope; const AEvaluate: TEvaluateProc); + constructor Create(const AMacroScope: IExecutionScope; const AMacroEvaluator: TMacroEvaluatorProc); destructor Destroy; override; - class function Expand(const MacroScope: IExecutionScope; const RootNode: IAstNode; const AEvaluate: TEvaluateProc): IAstNode; + class function Expand( + const MacroScope: IExecutionScope; + const RootNode: IAstNode; + const MacroEvaluator: TMacroEvaluatorProc + ): IAstNode; end; // Handles the expansion of macro calls within the AST. @@ -116,11 +118,11 @@ uses { TExpansionVisitor } -constructor TExpansionVisitor.Create(const AMacroScope: IExecutionScope; const AEvaluate: TEvaluateProc); +constructor TExpansionVisitor.Create(const AMacroScope: IExecutionScope; const AMacroEvaluator: TMacroEvaluatorProc); begin inherited Create; FMacroScope := AMacroScope; - FEvaluate := AEvaluate; + FMacroEvaluator := AMacroEvaluator; FRenameMap := TDictionary.Create; end; @@ -147,10 +149,10 @@ end; class function TExpansionVisitor.Expand( const MacroScope: IExecutionScope; const RootNode: IAstNode; - const AEvaluate: TEvaluateProc + const MacroEvaluator: TMacroEvaluatorProc ): IAstNode; begin - var expander := TExpansionVisitor.Create(MacroScope, AEvaluate); + var expander := TExpansionVisitor.Create(MacroScope, MacroEvaluator); try Result := expander.Accept(RootNode); finally @@ -171,7 +173,7 @@ begin if node.Kind = akUnquoteSplicing then begin var spliceExpr := node.AsUnquoteSplicing.Expression; - var evaluatedSpliceValue := FEvaluate(spliceExpr); + var evaluatedSpliceValue := FMacroEvaluator(FMacroScope, spliceExpr); if (not evaluatedSpliceValue.IsVoid) and (evaluatedSpliceValue.Kind = vkInterface) then begin @@ -282,7 +284,7 @@ begin end; // Evaluate the expression at compile time - value := FEvaluate(expr); + value := FMacroEvaluator(FMacroScope, expr); if value.Kind = vkInterface then begin @@ -438,17 +440,9 @@ begin for i := 0 to High(params) do expansionScope.Define(params[i].Name, TDataValue.FromIntf(Node.Arguments[i])); - // 3. Create simple callback for TExpansionVisitor - var evaluatorProc: TExpansionVisitor.TEvaluateProc := - function(const ANodeToEvaluate: IAstNode): TDataValue - begin - // Delegate complex binding/execution logic to the environment via FMacroEvaluator - Result := FMacroEvaluator(expansionScope, ANodeToEvaluate); - end; - // 4. Expand the Macro Body // We assume the macro body is a Quasiquote. We expand it using the visitor. - var expandedBody := TExpansionVisitor.Expand(expansionScope, macroDef.Body.AsQuasiquote.Expression, evaluatorProc); + var expandedBody := TExpansionVisitor.Expand(expansionScope, macroDef.Body.AsQuasiquote.Expression, FMacroEvaluator); // 5. Create a MacroExpansionNode to preserve source mapping var macroNode := TAst.MacroExpansionNode(Node, expandedBody);