Files
MycLib/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas
2026-01-13 23:17:32 +01:00

351 lines
12 KiB
ObjectPascal

unit Myc.Fmx.AstEditor.Visualizer;
interface
uses
System.SysUtils,
System.Classes,
FMX.Controls,
Myc.Data.Value,
Myc.Ast.Nodes,
Myc.Ast.Visitor,
Myc.Fmx.AstEditor.Render, // Virtual Engine
Myc.Fmx.AstEditor.Node, // View Nodes
Myc.Fmx.AstEditor.Workspace; // Host
type
// Implementation of the Factory/Visitor for the Virtual Tree
// Uses TAstVisitor<TAstViewNode> which uses closures for dispatch.
TAstVisualizer = class(TAstVisitor<TAstViewNode>, IAstVisualizer)
private
FExprDepth: Integer;
FParentNode: TVisualNode;
FWorkspace: TWorkspace;
function CallAccept(const Node: IAstNode): TAstViewNode;
// IAstVisualizer Implementation
function GetExprDepth: Integer;
function GetParentNode: TVisualNode;
function GetWorkspace: TWorkspace;
protected
// Setup registry using closures
procedure SetupHandlers; override;
// --- Visitor Implementations (Strict IAstNode signature) ---
function VisitConstant(const Node: IAstNode): TAstViewNode;
function VisitIdentifier(const Node: IAstNode): TAstViewNode;
function VisitKeyword(const Node: IAstNode): TAstViewNode;
// Unified List Handler
function VisitTuple(const Node: IAstNode): TAstViewNode;
// Elements
function VisitRecordField(const Node: IAstNode): TAstViewNode;
// Control Flow
function VisitIfExpression(const Node: IAstNode): TAstViewNode;
function VisitCondExpression(const Node: IAstNode): TAstViewNode;
function VisitBlockExpression(const Node: IAstNode): TAstViewNode;
function VisitRecurNode(const Node: IAstNode): TAstViewNode;
function VisitNop(const Node: IAstNode): TAstViewNode;
// Functions
function VisitLambdaExpression(const Node: IAstNode): TAstViewNode;
function VisitFunctionCall(const Node: IAstNode): TAstViewNode;
function VisitMacroExpansionNode(const Node: IAstNode): TAstViewNode;
// Declarations
function VisitVariableDeclaration(const Node: IAstNode): TAstViewNode;
function VisitAssignment(const Node: IAstNode): TAstViewNode;
function VisitMacroDefinition(const Node: IAstNode): TAstViewNode;
// Metaprogramming
function VisitQuasiquote(const Node: IAstNode): TAstViewNode;
function VisitUnquote(const Node: IAstNode): TAstViewNode;
function VisitUnquoteSplicing(const Node: IAstNode): TAstViewNode;
// Data Access
function VisitIndexer(const Node: IAstNode): TAstViewNode;
function VisitMemberAccess(const Node: IAstNode): TAstViewNode;
function VisitRecordLiteral(const Node: IAstNode): TAstViewNode;
// Series
function VisitCreateSeries(const Node: IAstNode): TAstViewNode;
function VisitAddSeriesItem(const Node: IAstNode): TAstViewNode;
// Pipes
function VisitPipe(const Node: IAstNode): TAstViewNode;
public
constructor Create(AWorkspace: TWorkspace; AParentNode: TVisualNode; AExprDepth: Integer);
destructor Destroy; override;
function Clone(ParentNode: TVisualNode; ExprDepth: Integer): IAstVisualizer;
property ExprDepth: Integer read GetExprDepth;
property ParentNode: TVisualNode read GetParentNode;
property Workspace: TWorkspace read GetWorkspace;
end;
implementation
uses
System.StrUtils,
Myc.Fmx.AstEditor.Handlers.Data,
Myc.Fmx.AstEditor.Handlers.Control,
Myc.Fmx.AstEditor.Handlers.Primitives,
Myc.Fmx.AstEditor.Handlers.Lists,
Myc.Fmx.AstEditor.Handlers.Pipes;
function IsStandardOperator(const Name: string): Boolean;
begin
Result := MatchStr(Name, ['+', '-', '*', '/', 'div', 'mod', '=', '<>', '<', '>', '<=', '>=', 'and', 'or', 'xor', 'not', 'shl', 'shr']);
end;
{ TAstVisualizer }
constructor TAstVisualizer.Create(AWorkspace: TWorkspace; AParentNode: TVisualNode; AExprDepth: Integer);
begin
inherited Create; // Calls SetupHandlers
FWorkspace := AWorkspace;
FParentNode := AParentNode;
FExprDepth := AExprDepth;
end;
destructor TAstVisualizer.Destroy;
begin
inherited;
end;
procedure TAstVisualizer.SetupHandlers;
begin
// Core Primitives
Register(akConstant, VisitConstant);
Register(akIdentifier, VisitIdentifier);
Register(akKeyword, VisitKeyword);
Register(akNop, VisitNop);
// Lists (Unified)
Register(akTuple, VisitTuple);
Register(akRecordField, VisitRecordField);
// Control Flow
Register(akIfExpression, VisitIfExpression);
Register(akCondExpression, VisitCondExpression);
Register(akBlockExpression, VisitBlockExpression);
Register(akRecur, VisitRecurNode);
// Functions
Register(akLambdaExpression, VisitLambdaExpression);
Register(akFunctionCall, VisitFunctionCall);
Register(akMacroExpansion, VisitMacroExpansionNode);
// Declarations
Register(akVariableDeclaration, VisitVariableDeclaration);
Register(akAssignment, VisitAssignment);
Register(akMacroDefinition, VisitMacroDefinition);
// Metaprogramming
Register(akQuasiquote, VisitQuasiquote);
Register(akUnquote, VisitUnquote);
Register(akUnquoteSplicing, VisitUnquoteSplicing);
// Data Access
Register(akIndexer, VisitIndexer);
Register(akMemberAccess, VisitMemberAccess);
Register(akRecordLiteral, VisitRecordLiteral);
// Series
Register(akCreateSeries, VisitCreateSeries);
Register(akAddSeriesItem, VisitAddSeriesItem);
// Pipes (Simplified)
Register(akPipe, VisitPipe);
end;
function TAstVisualizer.CallAccept(const Node: IAstNode): TAstViewNode;
var
dataValue: TDataValue;
begin
if not Assigned(Node) then
exit(nil);
dataValue := Node.Accept(Self);
if dataValue.Kind = vkGeneric then
Result := dataValue.AsGeneric<TAstViewNode>
else
Result := nil;
end;
function TAstVisualizer.Clone(ParentNode: TVisualNode; ExprDepth: Integer): IAstVisualizer;
begin
Result := TAstVisualizer.Create(FWorkspace, ParentNode, ExprDepth);
end;
function TAstVisualizer.GetExprDepth: Integer;
begin
Result := FExprDepth;
end;
function TAstVisualizer.GetParentNode: TVisualNode;
begin
Result := FParentNode;
end;
function TAstVisualizer.GetWorkspace: TWorkspace;
begin
Result := FWorkspace;
end;
// --- Visitor Implementations ---
function TAstVisualizer.VisitConstant(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TConstantNodeHandler.Create(Node.AsConstant));
end;
function TAstVisualizer.VisitIdentifier(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TIdentifierNodeHandler.Create(Node.AsIdentifier));
end;
function TAstVisualizer.VisitKeyword(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TKeywordNodeHandler.Create(Node.AsKeyword));
end;
function TAstVisualizer.VisitNop(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TNopNodeHandler.Create(Node.AsNop));
end;
function TAstVisualizer.VisitTuple(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TTupleHandler.Create(Node.AsTuple));
end;
function TAstVisualizer.VisitRecordField(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TRecordFieldHandler.Create(Node.AsRecordField));
end;
function TAstVisualizer.VisitBlockExpression(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TBlockExpressionNodeHandler.Create(Node.AsBlockExpression));
end;
function TAstVisualizer.VisitIfExpression(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TIfExpressionNodeHandler.Create(Node.AsIfExpression));
end;
function TAstVisualizer.VisitCondExpression(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TCondExpressionNodeHandler.Create(Node.AsCondExpression));
end;
function TAstVisualizer.VisitRecurNode(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TRecurNodeHandler.Create(Node.AsRecur));
end;
function TAstVisualizer.VisitLambdaExpression(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TLambdaExpressionNodeHandler.Create(Node.AsLambdaExpression));
end;
function TAstVisualizer.VisitFunctionCall(const Node: IAstNode): TAstViewNode;
var
C: IFunctionCallNode;
calleeName: string;
isOp: Boolean;
begin
C := Node.AsFunctionCall;
isOp := False;
if C.Callee.Kind = akIdentifier then
begin
calleeName := C.Callee.AsIdentifier.Name;
isOp := IsStandardOperator(calleeName);
end
else if C.Callee.Kind = akKeyword then
begin
calleeName := C.Callee.AsKeyword.Value.Name;
isOp := IsStandardOperator(calleeName);
end;
if isOp then
Result := TAstViewNode.Create(Self, TOperatorCallHandler.Create(C))
else
Result := TAstViewNode.Create(Self, TFunctionCallNodeHandler.Create(C));
end;
function TAstVisualizer.VisitMacroExpansionNode(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TMacroExpansionNodeHandler.Create(Node.AsMacroExpansion));
end;
function TAstVisualizer.VisitVariableDeclaration(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TVariableDeclarationNodeHandler.Create(Node.AsVariableDeclaration));
end;
function TAstVisualizer.VisitAssignment(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TAssignmentNodeHandler.Create(Node.AsAssignment));
end;
function TAstVisualizer.VisitMacroDefinition(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TMacroDefinitionNodeHandler.Create(Node.AsMacroDefinition));
end;
function TAstVisualizer.VisitQuasiquote(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TQuasiquoteNodeHandler.Create(Node.AsQuasiquote));
end;
function TAstVisualizer.VisitUnquote(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TUnquoteNodeHandler.Create(Node.AsUnquote));
end;
function TAstVisualizer.VisitUnquoteSplicing(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TUnquoteSplicingNodeHandler.Create(Node.AsUnquoteSplicing));
end;
function TAstVisualizer.VisitIndexer(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TIndexerNodeHandler.Create(Node.AsIndexer));
end;
function TAstVisualizer.VisitMemberAccess(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TMemberAccessNodeHandler.Create(Node.AsMemberAccess));
end;
function TAstVisualizer.VisitRecordLiteral(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TRecordLiteralNodeHandler.Create(Node.AsRecordLiteral));
end;
function TAstVisualizer.VisitCreateSeries(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TCreateSeriesNodeHandler.Create(Node.AsCreateSeries));
end;
function TAstVisualizer.VisitAddSeriesItem(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TAddSeriesItemNodeHandler.Create(Node.AsAddSeriesItem));
end;
function TAstVisualizer.VisitPipe(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TPipeNodeHandler.Create(Node.AsPipe));
end;
end.