Operator-Visualization in Ast editor
This commit is contained in:
@@ -154,6 +154,18 @@ type
|
|||||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Renders function calls as infix operators (e.g. "A + B" instead of "call + A B")
|
||||||
|
TOperatorCallHandler = class(TBaseNodeHandler<IFunctionCallNode>)
|
||||||
|
private
|
||||||
|
FArgumentNodes: TList<TAstViewNode>;
|
||||||
|
FCalleeName: string;
|
||||||
|
public
|
||||||
|
constructor Create(const ANode: IFunctionCallNode);
|
||||||
|
destructor Destroy; override;
|
||||||
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
|
end;
|
||||||
|
|
||||||
TMacroExpansionNodeHandler = class(TBaseNodeHandler<IMacroExpansionNode>)
|
TMacroExpansionNodeHandler = class(TBaseNodeHandler<IMacroExpansionNode>)
|
||||||
private
|
private
|
||||||
FExpandedBodyNode: TAstViewNode;
|
FExpandedBodyNode: TAstViewNode;
|
||||||
@@ -726,6 +738,94 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TOperatorCallHandler }
|
||||||
|
|
||||||
|
constructor TOperatorCallHandler.Create(const ANode: IFunctionCallNode);
|
||||||
|
begin
|
||||||
|
inherited Create(ANode);
|
||||||
|
FArgumentNodes := TList<TAstViewNode>.Create;
|
||||||
|
|
||||||
|
if ANode.Callee.Kind = akIdentifier then
|
||||||
|
FCalleeName := ANode.Callee.AsIdentifier.Name
|
||||||
|
else if ANode.Callee.Kind = akKeyword then
|
||||||
|
FCalleeName := ANode.Callee.AsKeyword.Value.Name
|
||||||
|
else
|
||||||
|
FCalleeName := '?';
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TOperatorCallHandler.Destroy;
|
||||||
|
begin
|
||||||
|
FArgumentNodes.Free;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TOperatorCallHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
|
var
|
||||||
|
visu: IAstVisualizer;
|
||||||
|
i: Integer;
|
||||||
|
argView: TAstViewNode;
|
||||||
|
opLabel: TTextNode;
|
||||||
|
begin
|
||||||
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
|
|
||||||
|
OwnerNode.Frameless := True;
|
||||||
|
OwnerNode.Orientation := loHorizontal;
|
||||||
|
OwnerNode.Alignment := laCenter;
|
||||||
|
|
||||||
|
if FNode.Arguments.Count = 1 then
|
||||||
|
begin
|
||||||
|
opLabel := OwnerNode.AddLabel(OwnerNode, FCalleeName);
|
||||||
|
opLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
|
opLabel.Color := TAlphaColors.Darkorange;
|
||||||
|
|
||||||
|
argView := visu.CallAccept(FNode.Arguments[0]);
|
||||||
|
FArgumentNodes.Add(argView);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
for i := 0 to FNode.Arguments.Count - 1 do
|
||||||
|
begin
|
||||||
|
if i > 0 then
|
||||||
|
begin
|
||||||
|
opLabel := OwnerNode.AddLabel(OwnerNode, ' ' + FCalleeName + ' ');
|
||||||
|
opLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
|
opLabel.Color := TAlphaColors.Darkorange;
|
||||||
|
opLabel.Margins := TMarginRect.Create(2, 2, 2, 2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
argView := visu.CallAccept(FNode.Arguments[i]);
|
||||||
|
FArgumentNodes.Add(argView);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if FNode.Arguments.Count = 0 then
|
||||||
|
begin
|
||||||
|
opLabel := OwnerNode.AddLabel(OwnerNode, FCalleeName);
|
||||||
|
opLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TOperatorCallHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
|
var
|
||||||
|
newArgs: TArray<IAstNode>;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
SetLength(newArgs, FArgumentNodes.Count);
|
||||||
|
for i := 0 to FArgumentNodes.Count - 1 do
|
||||||
|
newArgs[i] := FArgumentNodes[i].CreateAst;
|
||||||
|
|
||||||
|
Result :=
|
||||||
|
TAst.FunctionCall(
|
||||||
|
FNode.Identity,
|
||||||
|
FNode.Callee,
|
||||||
|
TArgumentList.Create(newArgs, FNode.Arguments.Identity),
|
||||||
|
FNode.StaticType,
|
||||||
|
FNode.IsTailCall,
|
||||||
|
FNode.StaticTarget,
|
||||||
|
FNode.IsTargetPure
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TMacroExpansionNodeHandler }
|
{ TMacroExpansionNodeHandler }
|
||||||
|
|
||||||
procedure TMacroExpansionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TMacroExpansionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
|
|||||||
@@ -87,6 +87,31 @@ type
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
// Helper to identify standard operators
|
||||||
|
function IsStandardOperator(const Name: string): Boolean;
|
||||||
|
begin
|
||||||
|
// You can extend this list based on your RTL
|
||||||
|
Result :=
|
||||||
|
(Name = '+')
|
||||||
|
or (Name = '-')
|
||||||
|
or (Name = '*')
|
||||||
|
or (Name = '/')
|
||||||
|
or (Name = 'div')
|
||||||
|
or (Name = 'mod')
|
||||||
|
or (Name = '=')
|
||||||
|
or (Name = '<>')
|
||||||
|
or (Name = '<')
|
||||||
|
or (Name = '>')
|
||||||
|
or (Name = '<=')
|
||||||
|
or (Name = '>=')
|
||||||
|
or (Name = 'and')
|
||||||
|
or (Name = 'or')
|
||||||
|
or (Name = 'xor')
|
||||||
|
or (Name = 'not')
|
||||||
|
or (Name = 'shl')
|
||||||
|
or (Name = 'shr');
|
||||||
|
end;
|
||||||
|
|
||||||
{ TAstVisualizer }
|
{ TAstVisualizer }
|
||||||
|
|
||||||
constructor TAstVisualizer.Create(AWorkspace: TWorkspace; AParentNode: TVisualNode; AExprDepth: Integer);
|
constructor TAstVisualizer.Create(AWorkspace: TWorkspace; AParentNode: TVisualNode; AExprDepth: Integer);
|
||||||
@@ -217,8 +242,28 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisualizer.VisitFunctionCall(const Node: IFunctionCallNode): TAstViewNode;
|
function TAstVisualizer.VisitFunctionCall(const Node: IFunctionCallNode): TAstViewNode;
|
||||||
|
var
|
||||||
|
calleeName: string;
|
||||||
|
isOp: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := TAstViewNode.Create(Self, TFunctionCallNodeHandler.Create(Node));
|
isOp := False;
|
||||||
|
|
||||||
|
// Check if callee is a simple identifier or keyword that matches an operator
|
||||||
|
if Node.Callee.Kind = akIdentifier then
|
||||||
|
begin
|
||||||
|
calleeName := Node.Callee.AsIdentifier.Name;
|
||||||
|
isOp := IsStandardOperator(calleeName);
|
||||||
|
end
|
||||||
|
else if Node.Callee.Kind = akKeyword then
|
||||||
|
begin
|
||||||
|
calleeName := Node.Callee.AsKeyword.Value.Name;
|
||||||
|
isOp := IsStandardOperator(calleeName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if isOp then
|
||||||
|
Result := TAstViewNode.Create(Self, TOperatorCallHandler.Create(Node))
|
||||||
|
else
|
||||||
|
Result := TAstViewNode.Create(Self, TFunctionCallNodeHandler.Create(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisualizer.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TAstViewNode;
|
function TAstVisualizer.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TAstViewNode;
|
||||||
|
|||||||
Reference in New Issue
Block a user