Simplified macro expansion
This commit is contained in:
@@ -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<string, string>;
|
||||
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<string, string>.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<IAstNode>(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);
|
||||
|
||||
Reference in New Issue
Block a user