Operator-Visualization in Ast editor
This commit is contained in:
@@ -154,6 +154,18 @@ type
|
||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||
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>)
|
||||
private
|
||||
FExpandedBodyNode: TAstViewNode;
|
||||
@@ -726,6 +738,94 @@ begin
|
||||
);
|
||||
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 }
|
||||
|
||||
procedure TMacroExpansionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||
|
||||
@@ -87,6 +87,31 @@ type
|
||||
|
||||
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 }
|
||||
|
||||
constructor TAstVisualizer.Create(AWorkspace: TWorkspace; AParentNode: TVisualNode; AExprDepth: Integer);
|
||||
@@ -217,8 +242,28 @@ begin
|
||||
end;
|
||||
|
||||
function TAstVisualizer.VisitFunctionCall(const Node: IFunctionCallNode): TAstViewNode;
|
||||
var
|
||||
calleeName: string;
|
||||
isOp: Boolean;
|
||||
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;
|
||||
|
||||
function TAstVisualizer.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TAstViewNode;
|
||||
|
||||
Reference in New Issue
Block a user