added macrodef
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user