unit Myc.Fmx.AstEditor.Handlers.Data; interface uses System.SysUtils, System.UITypes, Myc.Data.Keyword, Myc.Ast, Myc.Ast.Nodes, Myc.Fmx.AstEditor.Render, Myc.Fmx.AstEditor.Node; type // --- Declarations & Assignments --- TVariableDeclarationNodeHandler = class(TBaseNodeHandler) private FTargetNode: TAstViewNode; FInitializerNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TAssignmentNodeHandler = class(TBaseNodeHandler) private FTargetNode: TAstViewNode; FValueNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; // --- Metaprogramming --- TQuasiquoteNodeHandler = class(TBaseNodeHandler) private FExpressionNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TUnquoteNodeHandler = class(TBaseNodeHandler) private FExpressionNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TUnquoteSplicingNodeHandler = class(TBaseNodeHandler) private FExpressionNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; // --- Data Access & Structures --- TIndexerNodeHandler = class(TBaseNodeHandler) private FBaseNode: TAstViewNode; FIndexNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TMemberAccessNodeHandler = class(TBaseNodeHandler) private FBaseNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TRecordFieldHandler = class(TBaseNodeHandler) private FKeyLabel: TTextNode; FValueNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TRecordLiteralNodeHandler = class(TBaseNodeHandler) private FFieldsNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; // --- Series Operations --- TCreateSeriesNodeHandler = class(TBaseNodeHandler) private FDefNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TAddSeriesItemNodeHandler = class(TBaseNodeHandler) private FValueNode: TAstViewNode; FLookbackNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; implementation { TVariableDeclarationNodeHandler } procedure TVariableDeclarationNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; varLabel: TTextNode; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; varLabel := OwnerNode.AddLabel(OwnerNode, 'def'); // Changed 'var' to 'def' to match syntax varLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; FTargetNode := visu.CallAccept(FNode.Target); if Assigned(FNode.Initializer) then begin // Space before value OwnerNode.AddLabel(OwnerNode, ' '); FInitializerNode := visu.CallAccept(FNode.Initializer); end else FInitializerNode := nil; end; function TVariableDeclarationNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; var initAst: IAstNode; begin if Assigned(FInitializerNode) then initAst := FInitializerNode.CreateAst else initAst := nil; Result := TAst.VarDecl(FNode.Identity, FTargetNode.CreateAst, initAst, FNode.StaticType, FNode.IsBoxed); end; { TAssignmentNodeHandler } procedure TAssignmentNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; OwnerNode.AddLabel(OwnerNode, 'assign '); FTargetNode := visu.CallAccept(FNode.Target); OwnerNode.AddLabel(OwnerNode, ' '); FValueNode := visu.CallAccept(FNode.Value); end; function TAssignmentNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Assign(FNode.Identity, FTargetNode.CreateAst, FValueNode.CreateAst, FNode.StaticType); end; { TQuasiquoteNodeHandler } procedure TQuasiquoteNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleLabel: TTextNode; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; titleLabel := OwnerNode.AddLabel(OwnerNode, '`'); titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; FExpressionNode := visu.CallAccept(FNode.Expression); end; function TQuasiquoteNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Quasiquote(FNode.Identity, FExpressionNode.CreateAst); end; { TUnquoteNodeHandler } procedure TUnquoteNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; leftBracket: TTextNode; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; leftBracket := OwnerNode.AddLabel(OwnerNode, '~'); leftBracket.FontSettings.Font.Style := [TFontStyle.fsBold]; // Remove right margin to stick to expression leftBracket.Margins := TMarginRect.Create(cNodePadding, cTitleTopPadding, 0, cTitleBottomPadding); FExpressionNode := visu.CallAccept(FNode.Expression); end; function TUnquoteNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Unquote(FNode.Identity, FExpressionNode.CreateAst); end; { TUnquoteSplicingNodeHandler } procedure TUnquoteSplicingNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleLabel: TTextNode; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; titleLabel := OwnerNode.AddLabel(OwnerNode, '~@'); titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; // Remove right margin titleLabel.Margins := TMarginRect.Create(cNodePadding, cTitleTopPadding, 0, cTitleBottomPadding); FExpressionNode := visu.CallAccept(FNode.Expression); end; function TUnquoteSplicingNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.UnquoteSplicing(FNode.Identity, FExpressionNode.CreateAst.AsQuasiquote); end; { TIndexerNodeHandler } procedure TIndexerNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; OwnerNode.AddLabel(OwnerNode, 'get '); FBaseNode := visu.CallAccept(FNode.Base); OwnerNode.AddLabel(OwnerNode, ' '); FIndexNode := visu.CallAccept(FNode.Index); end; function TIndexerNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Indexer(FNode.Identity, FBaseNode.CreateAst, FIndexNode.CreateAst, FNode.StaticType); end; { TMemberAccessNodeHandler } procedure TMemberAccessNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; OwnerNode.AddLabel(OwnerNode, '.'); OwnerNode.AddLabel(OwnerNode, FNode.Member.Value.Name); OwnerNode.AddLabel(OwnerNode, ' '); FBaseNode := visu.CallAccept(FNode.Base); end; function TMemberAccessNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.MemberAccess(FNode.Identity, FBaseNode.CreateAst, TAst.Keyword(FNode.Member.Identity.AsKeyword), FNode.StaticType); end; { TRecordFieldHandler } procedure TRecordFieldHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; OwnerNode.Alignment := laCenter; FKeyLabel := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Key.Value.Name); FKeyLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; FKeyLabel.Color := TAlphaColors.Mediumvioletred; OwnerNode.AddLabel(OwnerNode, ' '); FValueNode := visu.CallAccept(FNode.Value); end; function TRecordFieldHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.RecordField(FNode.Identity, FNode.Key, FValueNode.CreateAst); end; { TRecordLiteralNodeHandler } procedure TRecordLiteralNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; braceL: TTextNode; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; OwnerNode.Alignment := laFlush; // Align left // Visual hint: Curly braces for record braceL := OwnerNode.AddLabel(OwnerNode, '{'); braceL.FontSettings.Font.Style := [TFontStyle.fsBold]; // Delegate to Fields Tuple (previously RecordFieldList) FFieldsNode := visu.CallAccept(FNode.Fields); OwnerNode.AddLabel(OwnerNode, '}'); end; function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.RecordLiteral( FNode.Identity, FFieldsNode.CreateAst.AsTuple, FNode.ScalarDefinition, FNode.GenericDefinition, FNode.StaticType ); end; { TCreateSeriesNodeHandler } procedure TCreateSeriesNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleLabel: TTextNode; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'new-series'); titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; // Now visualize the definition node (likely a Tuple or Keyword) FDefNode := visu.CallAccept(FNode.DefinitionNode); end; function TCreateSeriesNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.CreateSeries(FNode.Identity, FDefNode.CreateAst, FNode.RecordDefinition, FNode.StaticType); end; { TAddSeriesItemNodeHandler } procedure TAddSeriesItemNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleLabel: TTextNode; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'add-item: ' + FNode.Series.Name); titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; FValueNode := visu.CallAccept(FNode.Value); if Assigned(FNode.Lookback) then begin OwnerNode.AddLabel(OwnerNode, 'Lookback:'); FLookbackNode := visu.CallAccept(FNode.Lookback); end else FLookbackNode := nil; end; function TAddSeriesItemNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; var lookbackAst: IAstNode; begin if Assigned(FLookbackNode) then lookbackAst := FLookbackNode.CreateAst else lookbackAst := nil; Result := TAst.AddSeriesItem( FNode.Identity, FNode.Series, // Reuse original Series Identifier Node FValueNode.CreateAst, lookbackAst, FNode.StaticType ); end; end.