1st full macro expander

This commit is contained in:
Michael Schimmel
2025-10-03 19:46:30 +02:00
parent bb0ecda6be
commit d9219474e0
16 changed files with 700 additions and 323 deletions
+50 -43
View File
@@ -49,25 +49,24 @@ type
// Stack management for tail-call state is centralized here.
function Accept(const Node: IAstNode): TDataValue; override;
// The binder overrides specific visit methods to enrich the AST.
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override;
public
constructor Create(const AInitialScope: IExecutionScope);
destructor Destroy; override;
function Execute(const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
// The binder overrides specific transform methods to enrich the AST.
function TransformIdentifier(const Node: IIdentifierNode): IIdentifierNode; override;
function TransformVariableDeclaration(const Node: IVariableDeclarationNode): IVariableDeclarationNode; override;
function TransformAssignment(const Node: IAssignmentNode): IAssignmentNode; override;
function TransformLambdaExpression(const Node: ILambdaExpressionNode): ILambdaExpressionNode; override;
function TransformMacroDefinition(const Node: IMacroDefinitionNode): IMacroDefinitionNode; override;
function TransformFunctionCall(const Node: IFunctionCallNode): IFunctionCallNode; override;
function TransformRecur(const Node: IRecurNode): IRecurNode; override;
function TransformBlockExpression(const Node: IBlockExpressionNode): IBlockExpressionNode; override;
function TransformIfExpression(const Node: IIfExpressionNode): IIfExpressionNode; override;
function TransformTernaryExpression(const Node: ITernaryExpressionNode): ITernaryExpressionNode; override;
function TransformBinaryExpression(const Node: IBinaryExpressionNode): IBinaryExpressionNode; override;
function TransformUnaryExpression(const Node: IUnaryExpressionNode): IUnaryExpressionNode; override;
end;
TBoundIdentifierNode = class(TIdentifierNode)
@@ -285,9 +284,10 @@ begin
Result := True;
end;
function TAstBinder.TransformIdentifier(const Node: IIdentifierNode): IIdentifierNode;
function TAstBinder.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
var
adr: TResolvedAddress;
boundNode: IIdentifierNode;
begin
adr := FCurrentDescriptor.FindSymbol(Node.Name);
if adr.Kind = akLocalOrParent then
@@ -306,22 +306,24 @@ begin
upvalue.Map.Add(adr, upvalueIndex);
end;
Result := TBoundIdentifierNode.Create(Node, TResolvedAddress.Create(akUpvalue, 0, upvalueIndex));
boundNode := TBoundIdentifierNode.Create(Node, TResolvedAddress.Create(akUpvalue, 0, upvalueIndex));
end
else
Result := TBoundIdentifierNode.Create(Node, adr);
boundNode := TBoundIdentifierNode.Create(Node, adr);
Result := TDataValue.FromIntf<IIdentifierNode>(boundNode);
end
else
raise Exception.CreateFmt('Undefined identifier: "%s"', [Node.Name]);
end;
function TAstBinder.TransformVariableDeclaration(const Node: IVariableDeclarationNode): IVariableDeclarationNode;
function TAstBinder.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
var
initializer: IAstNode;
slotIndex: Integer;
address: TResolvedAddress;
boundIdentifier: IIdentifierNode;
isBoxed: Boolean;
boundDecl: IVariableDeclarationNode;
begin
if not IsValidIdentifier(Node.Identifier.Name) then
raise Exception.CreateFmt('Invalid identifier name: "%s".', [Node.Identifier.Name]);
@@ -340,28 +342,29 @@ begin
isBoxed := (FBoxedDeclarations <> nil) and FBoxedDeclarations.Contains(Node);
// Always create a bound declaration node, passing the IsBoxed flag.
Result := TBoundVariableDeclarationNode.Create(boundIdentifier, initializer, isBoxed);
boundDecl := TBoundVariableDeclarationNode.Create(boundIdentifier, initializer, isBoxed);
Result := TDataValue.FromIntf<IVariableDeclarationNode>(boundDecl);
end;
function TAstBinder.TransformAssignment(const Node: IAssignmentNode): IAssignmentNode;
function TAstBinder.VisitAssignment(const Node: IAssignmentNode): TDataValue;
begin
FNextIsTail := False;
Result := inherited TransformAssignment(Node);
Result := inherited VisitAssignment(Node);
end;
function TAstBinder.TransformBinaryExpression(const Node: IBinaryExpressionNode): IBinaryExpressionNode;
function TAstBinder.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
begin
FNextIsTail := False;
Result := inherited TransformBinaryExpression(Node);
Result := inherited VisitBinaryExpression(Node);
end;
function TAstBinder.TransformUnaryExpression(const Node: IUnaryExpressionNode): IUnaryExpressionNode;
function TAstBinder.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
begin
FNextIsTail := False;
Result := inherited TransformUnaryExpression(Node);
Result := inherited VisitUnaryExpression(Node);
end;
function TAstBinder.TransformLambdaExpression(const Node: ILambdaExpressionNode): ILambdaExpressionNode;
function TAstBinder.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
var
i: integer;
boundParams: TArray<IIdentifierNode>;
@@ -370,6 +373,7 @@ var
upvalues: TArray<TResolvedAddress>;
hasNestedLambdas: Boolean;
lastNestedLambdaCount: Integer;
boundLambda: ILambdaExpressionNode;
begin
FUpvalueStack.Push(TUpvalueMapping.Create);
try
@@ -415,14 +419,16 @@ begin
end;
inc(FNestedLambdaCount);
Result := TBoundLambdaExpressionNode.Create(Node, boundBody, boundParams, lambdaScope, upvalues, hasNestedLambdas);
boundLambda := TBoundLambdaExpressionNode.Create(Node, boundBody, boundParams, lambdaScope, upvalues, hasNestedLambdas);
Result := TDataValue.FromIntf<ILambdaExpressionNode>(boundLambda);
end;
function TAstBinder.TransformFunctionCall(const Node: IFunctionCallNode): IFunctionCallNode;
function TAstBinder.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
var
isTailCall: Boolean;
callee: IAstNode;
args: TArray<IAstNode>;
boundCall: IFunctionCallNode;
begin
isTailCall := FIsTailStack.Peek;
@@ -430,19 +436,20 @@ begin
callee := Accept(Node.Callee).AsIntf<IAstNode>;
args := TransformNodes<IAstNode>(Node.Arguments);
Result := TBoundFunctionCallNode.Create(Node, callee, args, isTailCall);
boundCall := TBoundFunctionCallNode.Create(Node, callee, args, isTailCall);
Result := TDataValue.FromIntf<IFunctionCallNode>(boundCall);
end;
function TAstBinder.TransformRecur(const Node: IRecurNode): IRecurNode;
function TAstBinder.VisitRecurNode(const Node: IRecurNode): TDataValue;
begin
if not FIsTailStack.Peek then
raise Exception.Create('''recur'' can only be used in a tail position.');
FNextIsTail := False;
Result := inherited TransformRecur(Node);
Result := inherited VisitRecurNode(Node);
end;
function TAstBinder.TransformBlockExpression(const Node: IBlockExpressionNode): IBlockExpressionNode;
function TAstBinder.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
var
exprs: TArray<IAstNode>;
i: Integer;
@@ -450,16 +457,16 @@ var
begin
isContextTail := FIsTailStack.Peek;
SetLength(exprs, Node.Expressions.Count);
for i := 0 to Node.Expressions.Count - 1 do
SetLength(exprs, Length(Node.Expressions));
for i := 0 to High(exprs) do
begin
FNextIsTail := isContextTail and (i = Node.Expressions.Count - 1);
FNextIsTail := isContextTail and (i = High(exprs));
exprs[i] := Accept(Node.Expressions[i]).AsIntf<IAstNode>;
end;
Result := TAst.Block(exprs);
Result := TDataValue.FromIntf<IBlockExpressionNode>(TAst.Block(exprs));
end;
function TAstBinder.TransformIfExpression(const Node: IIfExpressionNode): IIfExpressionNode;
function TAstBinder.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
var
isContextTail: Boolean;
condition, thenBranch, elseBranch: IAstNode;
@@ -474,18 +481,18 @@ begin
elseBranch := Accept(Node.ElseBranch).AsIntf<IAstNode>;
if (condition <> Node.Condition) or (thenBranch <> Node.ThenBranch) or (elseBranch <> Node.ElseBranch) then
Result := TAst.IfExpr(condition, thenBranch, elseBranch)
Result := TDataValue.FromIntf<IIfExpressionNode>(TAst.IfExpr(condition, thenBranch, elseBranch))
else
Result := Node;
Result := TDataValue.FromIntf<IIfExpressionNode>(Node);
end;
function TAstBinder.TransformMacroDefinition(const Node: IMacroDefinitionNode): IMacroDefinitionNode;
function TAstBinder.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
begin
// The binder runs after the macro expander. It should never see a macro definition.
raise Exception.Create('IMacroDefinitionNode found in AST after macro expansion phase.');
end;
function TAstBinder.TransformTernaryExpression(const Node: ITernaryExpressionNode): ITernaryExpressionNode;
function TAstBinder.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
var
isContextTail: Boolean;
condition, thenBranch, elseBranch: IAstNode;
@@ -500,9 +507,9 @@ begin
elseBranch := Accept(Node.ElseBranch).AsIntf<IAstNode>;
if (condition <> Node.Condition) or (thenBranch <> Node.ThenBranch) or (elseBranch <> Node.ElseBranch) then
Result := TAst.TernaryExpr(condition, thenBranch, elseBranch)
Result := TDataValue.FromIntf<ITernaryExpressionNode>(TAst.TernaryExpr(condition, thenBranch, elseBranch))
else
Result := Node;
Result := TDataValue.FromIntf<ITernaryExpressionNode>(Node);
end;
end.