added macrodef

This commit is contained in:
Michael Schimmel
2025-10-03 13:49:12 +02:00
parent d47c1417f5
commit fd97799b7b
10 changed files with 382 additions and 5 deletions
+28
View File
@@ -20,6 +20,7 @@ type
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
@@ -164,6 +165,33 @@ begin
end;
end;
function TAstToTextVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
var
i: Integer;
sb: TStringBuilder;
begin
// Added text representation for macro definitions.
sb := TStringBuilder.Create;
try
sb.Append('defmacro ');
sb.Append(Node.Name.Name);
sb.Append('(');
if Length(Node.Parameters) > 0 then
begin
for i := 0 to High(Node.Parameters) do
begin
sb.Append(Node.Parameters[i].Name);
if i < High(Node.Parameters) then
sb.Append(', ');
end;
end;
sb.Append(') => {...}');
Result := sb.ToString;
finally
sb.Free;
end;
end;
function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
var
baseStr: string;
+98
View File
@@ -114,6 +114,7 @@ type
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
@@ -1147,6 +1148,103 @@ begin
Result := TDataValue.Void;
end;
function TAstToAuraNodeVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
var
paramStr: String;
macroNode: TAuraNode;
i: Integer;
childVisitor: TAstToAuraNodeVisitor;
childStartPos: TPointF;
maxRight, maxBottom: Single;
control: TControl;
childLastResult: TAuraNodeResult;
entryNode, exitNode: TAuraNode;
paramDescriptor: IScopeDescriptor;
begin
// Create a string representation of the parameters for the node title.
paramStr := '(';
if Length(Node.Parameters) > 0 then
begin
paramStr := paramStr + Node.Parameters[0].Name;
for i := 1 to High(Node.Parameters) do
paramStr := paramStr + ', ' + Node.Parameters[i].Name;
end;
paramStr := paramStr + ')';
// 1. Create the main container node for the macro definition.
macroNode := BuildNodeControl('defmacro: ' + Node.Name.Name, paramStr);
macroNode.Position.Point := FCurrentPos;
// A macro definition is a statement, so it has execution pins.
CreateEntry(macroNode);
// 2. Create a temporary scope descriptor for the macro's parameters.
// This allows the child visitor to correctly visualize parameter nodes.
paramDescriptor := TScope.CreateDescriptor(nil);
for i := 0 to High(Node.Parameters) do
paramDescriptor.Define(Node.Parameters[i].Name);
// 3. Create a child visitor for the new scope within the macro's body.
const pinNodeHeight = cPinSize + cVerticalPadding;
childStartPos := TPointF.Create(FSpacing.X, FSpacing.Y + pinNodeHeight);
childVisitor := TAstToAuraNodeVisitor.Create(FWorkspace, macroNode, childStartPos, FConnections, [], FMode, Self, nil, paramDescriptor);
// 4. Create the visual nodes for the parameters inside the macro's scope.
for i := 0 to High(Node.Parameters) do
begin
var param := Node.Parameters[i];
var paramNode := childVisitor.CreateNodeControl('Parameter', param.Name);
var paramResult: TAuraNodeResult;
paramResult.LayoutNode := paramNode;
paramResult.OutputPin := childVisitor.CreateOutput(paramNode);
childVisitor.FinalizeNodeLayout(paramNode);
// Cache the parameter node by its slot index for lookups within the body.
if i < Length(childVisitor.FSlotCache) then
childVisitor.FSlotCache[i] := paramResult;
end;
// 5. Let the child visitor render the macro's body.
Node.Body.Accept(childVisitor);
childLastResult := childVisitor.FLastResult;
// 6. Resize the container to fit all internally generated nodes.
maxRight := 0;
maxBottom := 0;
for control in macroNode.Controls do
begin
if control is TAuraNode then
begin
maxRight := Max(maxRight, control.Position.X + control.Width);
maxBottom := Max(maxBottom, control.Position.Y + control.Height);
end;
end;
macroNode.Width := Max(macroNode.Width, maxRight + FSpacing.X);
macroNode.Height := Max(macroNode.Height, maxBottom + FSpacing.Y);
// 7. Create an internal 'expansion' exit point, showing what the macro produces.
exitNode := BuildNodeControl('Expansion', '');
exitNode.Parent := macroNode;
exitNode.Height := pinNodeHeight;
// Connect the data flow (the result of the last expression in the body) to the expansion node.
if Assigned(childLastResult.OutputPin) then
begin
var dataResultPin := childVisitor.CreateInput(exitNode, 'AST');
FConnections.Add(TPinConnection.Create(childLastResult.OutputPin, dataResultPin));
end;
childVisitor.FinalizeNodeLayout(exitNode);
macroNode.Height := Max(macroNode.Height, maxBottom + FSpacing.Y + exitNode.Height);
exitNode.Position.Point := TPointF.Create(FSpacing.X, macroNode.Height - exitNode.Height - FSpacing.Y);
// 8. Finalize the main visitor state.
FCurrentPos.Y := macroNode.Position.Y + macroNode.Height + FSpacing.Y;
FLastResult.LayoutNode := macroNode;
FLastResult.OutputPin := nil; // A macro definition itself does not return a value.
CreateExit(macroNode, ''); // Execution flow continues after the definition.
FinalizeNodeLayout(macroNode);
Result := TDataValue.Void;
end;
function TAstToAuraNodeVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
var
details: string;
+7
View File
@@ -60,6 +60,7 @@ type
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;
@@ -478,6 +479,12 @@ begin
Result := Node;
end;
function TAstBinder.TransformMacroDefinition(const Node: IMacroDefinitionNode): IMacroDefinitionNode;
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;
var
isContextTail: Boolean;
+28
View File
@@ -41,6 +41,7 @@ type
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
@@ -322,6 +323,33 @@ begin
Result := TDataValue.Void;
end;
function TAstDumper.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
var
param: IIdentifierNode;
begin
Log('MacroDefinition');
Indent;
Log('Name:');
Indent;
Node.Name.Accept(Self);
Unindent;
Log('Parameters:');
Indent;
for param in Node.Parameters do
param.Accept(Self);
Unindent;
Log('Body:');
Indent;
Node.Body.Accept(Self);
Unindent;
Unindent;
Result := TDataValue.Void;
end;
function TAstDumper.VisitIndexer(const Node: IIndexerNode): TDataValue;
begin
Log('Indexer');
+9
View File
@@ -35,6 +35,7 @@ type
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
@@ -240,6 +241,14 @@ begin
Result := closure;
end;
function TEvaluatorVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
begin
// Macro definitions are compile-time constructs and should have been
// processed and removed from the AST by the TMacroExpander.
// If we encounter one here, it's a compiler pipeline error.
raise Exception.Create('Macro definitions cannot be evaluated at runtime.');
end;
function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
var
calleeValue: TDataValue;
+59
View File
@@ -34,6 +34,7 @@ type
function JsonToIfExprNode(const AObj: TJSONObject): IIfExpressionNode;
function JsonToTernaryExprNode(const AObj: TJSONObject): ITernaryExpressionNode;
function JsonToLambdaExprNode(const AObj: TJSONObject): ILambdaExpressionNode;
function JsonToMacroDefNode(const AObj: TJSONObject): IMacroDefinitionNode;
function JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
function JsonToRecurNode(const AObj: TJSONObject): IRecurNode;
function JsonToBlockNode(const AObj: TJSONObject): IBlockExpressionNode;
@@ -53,6 +54,7 @@ type
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): 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;
@@ -258,6 +260,41 @@ begin
Result := TDataValue.Void;
end;
function TJsonAstConverter.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
var
obj, nameObj, bodyObj: TJSONObject;
paramsArray: TJSONArray;
tempParams: TArray<TJSONObject>;
param: IIdentifierNode;
i: Integer;
begin
// Added serialization for macro definitions.
Node.Name.Accept(Self);
for param in Node.Parameters do
param.Accept(Self);
Node.Body.Accept(Self);
bodyObj := FJsonObjectStack.Pop;
SetLength(tempParams, Length(Node.Parameters));
for i := High(tempParams) downto 0 do
tempParams[i] := FJsonObjectStack.Pop;
nameObj := FJsonObjectStack.Pop;
paramsArray := TJSONArray.Create;
for i := 0 to High(tempParams) do
paramsArray.Add(tempParams[i]);
obj := TJSONObject.Create;
obj.AddPair('NodeType', TJSONString.Create('MacroDef'));
obj.AddPair('Name', nameObj);
obj.AddPair('Parameters', paramsArray);
obj.AddPair('Body', bodyObj);
FJsonObjectStack.Push(obj);
Result := TDataValue.Void;
end;
function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
var
obj, calleeObj: TJSONObject;
@@ -589,6 +626,26 @@ begin
Result := TAst.LambdaExpr(params, body);
end;
function TJsonAstConverter.JsonToMacroDefNode(const AObj: TJSONObject): IMacroDefinitionNode;
var
name: IIdentifierNode;
params: TArray<IIdentifierNode>;
body: IAstNode;
paramArray: TJSONArray;
i: Integer;
begin
// Added deserialization for macro definitions.
name := JsonToIdentifierNode(AObj.GetValue('Name') as TJSONObject);
paramArray := AObj.GetValue<TJSONArray>('Parameters');
SetLength(params, paramArray.Count);
for i := 0 to paramArray.Count - 1 do
params[i] := JsonToIdentifierNode(paramArray.Items[i] as TJSONObject);
body := JsonToNode(AObj.GetValue('Body'));
Result := TAst.MacroDef(name, params, body);
end;
function TJsonAstConverter.JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
var
callee: IAstNode;
@@ -715,6 +772,8 @@ begin
Result := JsonToTernaryExprNode(obj)
else if nodeType = 'LambdaExpr' then
Result := JsonToLambdaExprNode(obj)
else if nodeType = 'MacroDef' then
Result := JsonToMacroDefNode(obj)
else if nodeType = 'FunctionCall' then
Result := JsonToFunctionCallNode(obj)
else if nodeType = 'Recur' then
+13
View File
@@ -23,6 +23,7 @@ type
IBlockExpressionNode = interface;
IVariableDeclarationNode = interface;
IAssignmentNode = interface;
IMacroDefinitionNode = interface;
IIndexerNode = interface;
IMemberAccessNode = interface;
ICreateSeriesNode = interface;
@@ -57,6 +58,7 @@ type
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
function VisitAssignment(const Node: IAssignmentNode): TDataValue;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
function VisitIndexer(const Node: IIndexerNode): TDataValue;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
@@ -177,6 +179,17 @@ type
property Value: IAstNode read GetValue;
end;
IMacroDefinitionNode = interface(IAstNode)
{$region 'private'}
function GetName: IIdentifierNode;
function GetParameters: TArray<IIdentifierNode>;
function GetBody: IAstNode;
{$endregion}
property Name: IIdentifierNode read GetName;
property Parameters: TArray<IIdentifierNode> read GetParameters;
property Body: IAstNode read GetBody;
end;
IIndexerNode = interface(IAstNode)
{$region 'private'}
function GetBase: IAstNode;
+55
View File
@@ -108,6 +108,7 @@ type
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
@@ -359,6 +360,20 @@ begin
raise Exception.Create('Syntax Error: Expected an identifier for def statement.');
Result := TAst.VarDecl(IIdentifierNode(tailNodes[0]), IfThen(Length(tailNodes) > 1, tailNodes[1], nil));
end
else if SameText(head.Token.Text, 'defmacro') then
begin
// (defmacro name [params] body)
if (Length(tailNodes) <> 3) or (tailTokens[0].Kind <> tkIdentifier) then
raise Exception.Create('Syntax Error: ''defmacro'' requires a name, a parameter list, and a body.');
if elements[1].Node <> nil then
raise Exception.Create('Syntax Error: Expected a parameter list [...] after macro name.');
var macroName := IIdentifierNode(tailNodes[0]);
var macroParams := elements[1].Params;
var macroBody := tailNodes[2];
Result := TAst.MacroDef(macroName, macroParams, macroBody);
end
else if SameText(head.Token.Text, 'assign') then
begin
if tailTokens[0].Kind <> tkIdentifier then
@@ -424,6 +439,19 @@ var
i64: Int64;
dbl: Double;
begin
// TODO: Implement reader macros for quasiquoting here.
// The current lexer will tokenize `, ~, and ~@ as identifiers.
// Check for them here and wrap the subsequent expression accordingly.
// Example:
// if FCurrentToken.Text = '`' then
// begin
// NextToken;
// var exprToQuote := ParseExpression;
// Result.Node := TAst.Quasiquote(exprToQuote.Node);
// exit;
// end;
// (This requires IQuasiquoteNode and TAst.Quasiquote to be defined first).
Result.Token := FCurrentToken;
case FCurrentToken.Kind of
tkNumber:
@@ -606,6 +634,33 @@ begin
Result := TDataValue.Void;
end;
function TPrettyPrintVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
var
param: IIdentifierNode;
sb: TStringBuilder;
begin
// Added visitor for pretty printing macro definitions.
sb := TStringBuilder.Create;
try
for param in Node.Parameters do
sb.Append(param.Name + ' ');
if sb.Length > 0 then
sb.Remove(sb.Length - 1, 1);
Append('(defmacro ' + Node.Name.Name + ' [' + sb.ToString + ']');
finally
sb.Free;
end;
Indent;
NewLine;
Node.Body.Accept(Self);
Unindent;
NewLine;
Append(')');
Result := TDataValue.Void;
end;
function TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
var
arg: IAstNode;
+21
View File
@@ -24,6 +24,7 @@ type
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; virtual; abstract;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; virtual; abstract;
function VisitAssignment(const Node: IAssignmentNode): TDataValue; virtual; abstract;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; virtual; abstract;
function VisitIndexer(const Node: IIndexerNode): TDataValue; virtual; abstract;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; virtual; abstract;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; virtual; abstract;
@@ -57,6 +58,7 @@ type
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override; final;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override; final;
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override; final;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override; final;
function VisitIndexer(const Node: IIndexerNode): TDataValue; override; final;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override; final;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override; final;
@@ -76,6 +78,7 @@ type
function TransformBlockExpression(const Node: IBlockExpressionNode): IBlockExpressionNode; virtual;
function TransformVariableDeclaration(const Node: IVariableDeclarationNode): IVariableDeclarationNode; virtual;
function TransformAssignment(const Node: IAssignmentNode): IAssignmentNode; virtual;
function TransformMacroDefinition(const Node: IMacroDefinitionNode): IMacroDefinitionNode; virtual;
function TransformIndexer(const Node: IIndexerNode): IIndexerNode; virtual;
function TransformMemberAccess(const Node: IMemberAccessNode): IMemberAccessNode; virtual;
function TransformCreateSeries(const Node: ICreateSeriesNode): ICreateSeriesNode; virtual;
@@ -234,6 +237,18 @@ begin
Result := TAst.Assign(identifier, value);
end;
function TAstTransformer.TransformMacroDefinition(const Node: IMacroDefinitionNode): IMacroDefinitionNode;
begin
// Added identity transform for macro definitions.
var name := Accept(Node.Name).AsIntf<IIdentifierNode>;
var parameters := TransformNodes<IIdentifierNode>(Node.Parameters);
var body := Accept(Node.Body).AsIntf<IAstNode>;
if (name = Node.Name) and (parameters = Node.Parameters) and (body = Node.Body) then
Result := Node
else
Result := TAst.MacroDef(name, parameters, body);
end;
function TAstTransformer.TransformIndexer(const Node: IIndexerNode): IIndexerNode;
begin
var base := Accept(Node.Base).AsIntf<IAstNode>;
@@ -360,6 +375,12 @@ begin
Result := TDataValue.FromIntf<IAssignmentNode>(TransformAssignment(Node));
end;
function TAstTransformer.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
begin
// Added visit method for macro definitions.
Result := TDataValue.FromIntf<IMacroDefinitionNode>(TransformMacroDefinition(Node));
end;
function TAstTransformer.VisitIndexer(const Node: IIndexerNode): TDataValue;
begin
Result := TDataValue.FromIntf<IIndexerNode>(TransformIndexer(Node));
+64 -5
View File
@@ -36,6 +36,11 @@ type
class function IfExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): IIfExpressionNode; static;
class function TernaryExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): ITernaryExpressionNode; static;
class function LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode; static;
class function MacroDef(
const AName: IIdentifierNode;
const AParameters: TArray<IIdentifierNode>;
const ABody: IAstNode
): IMacroDefinitionNode; static;
class function FunctionCall(const ACallee: IAstNode; const AArguments: TArray<IAstNode>): IFunctionCallNode; static;
class function Recur(const AArguments: array of IAstNode): IRecurNode; static;
class function Block(const AExpressions: array of IAstNode): IBlockExpressionNode; static;
@@ -141,6 +146,19 @@ type
property Parameters: TArray<IIdentifierNode> read FParameters;
end;
TMacroDefinitionNode = class(TAstNode, IMacroDefinitionNode)
private
FName: IIdentifierNode;
FParameters: TArray<IIdentifierNode>;
FBody: IAstNode;
function GetName: IIdentifierNode;
function GetParameters: TArray<IIdentifierNode>;
function GetBody: IAstNode;
public
constructor Create(const AName: IIdentifierNode; const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TFunctionCallNode = class(TAstNode, IFunctionCallNode)
private
FCallee: IAstNode;
@@ -428,6 +446,37 @@ begin
Result := FParameters;
end;
{ TMacroDefinitionNode }
constructor TMacroDefinitionNode.Create(const AName: IIdentifierNode; const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
begin
// Added concrete class for macro definitions.
inherited Create;
FName := AName;
FParameters := AParameters;
FBody := ABody;
end;
function TMacroDefinitionNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitMacroDefinition(Self);
end;
function TMacroDefinitionNode.GetBody: IAstNode;
begin
Result := FBody;
end;
function TMacroDefinitionNode.GetName: IIdentifierNode;
begin
Result := FName;
end;
function TMacroDefinitionNode.GetParameters: TArray<IIdentifierNode>;
begin
Result := FParameters;
end;
{ TFunctionCallNode }
constructor TFunctionCallNode.Create(const ACallee: IAstNode; const AArguments: TArray<IAstNode>);
@@ -751,6 +800,21 @@ begin
Result := TIndexerNode.Create(ABase, AIndex);
end;
class function TAst.LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode;
begin
Result := TLambdaExpressionNode.Create(AParameters, ABody);
end;
class function TAst.MacroDef(
const AName: IIdentifierNode;
const AParameters: TArray<IIdentifierNode>;
const ABody: IAstNode
): IMacroDefinitionNode;
begin
// Added factory for macro definitions.
Result := TMacroDefinitionNode.Create(AName, AParameters, ABody);
end;
class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IIdentifierNode): IMemberAccessNode;
begin
Result := TMemberAccessNode.Create(ABase, AMember);
@@ -777,11 +841,6 @@ begin
Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch);
end;
class function TAst.LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode;
begin
Result := TLambdaExpressionNode.Create(AParameters, ABody);
end;
class function TAst.UnaryExpr(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode): IUnaryExpressionNode;
begin
Result := TUnaryExpressionNode.Create(AOperator, ARight);