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) 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; TSeriesLengthNodeHandler = class(TBaseNodeHandler) 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, 'var'); varLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; FTargetNode := visu.CallAccept(FNode.Target); if Assigned(FNode.Initializer) then begin 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; 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 := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Quasiquote'); 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, rightBracket: TTextNode; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; leftBracket := OwnerNode.AddLabel(OwnerNode, '<'); // We cannot assign to fields of record properties directly. // Replace the entire margin record. // Default from AddLabel is (cNodePadding, cTitleTopPadding, cNodePadding, cTitleBottomPadding) // We want Right Margin = 0. leftBracket.Margins := TMarginRect.Create(cNodePadding, cTitleTopPadding, 0, cTitleBottomPadding); FExpressionNode := visu.CallAccept(FNode.Expression); rightBracket := OwnerNode.AddLabel(OwnerNode, '>'); // We want Left Margin = 0. rightBracket.Margins := TMarginRect.Create(0, cTitleTopPadding, cNodePadding, cTitleBottomPadding); 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 := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Unquote-Splicing'); titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; 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; FBaseNode := visu.CallAccept(FNode.Base); OwnerNode.AddLabel(OwnerNode, '['); FIndexNode := visu.CallAccept(FNode.Index); OwnerNode.AddLabel(OwnerNode, ']'); 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; FBaseNode := visu.CallAccept(FNode.Base); OwnerNode.AddLabel(OwnerNode, '.'); OwnerNode.AddLabel(OwnerNode, FNode.Member.Value.Name); 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; 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; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; OwnerNode.Alignment := laFlush; // Delegate to RecordFieldList FFieldsNode := visu.CallAccept(FNode.Fields); end; function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.RecordLiteral( FNode.Identity, FFieldsNode.CreateAst.AsRecordFieldList, FNode.ScalarDefinition, FNode.GenericDefinition, FNode.StaticType ); end; { TCreateSeriesNodeHandler } procedure TCreateSeriesNodeHandler.BuildUI(OwnerNode: TAstViewNode); var titleLabel: TTextNode; begin OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Create Series: ' + FNode.Definition); titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; end; function TCreateSeriesNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.CreateSeries(FNode.Identity.AsDefinition, 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 to: ' + FNode.Series.Name); titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; FValueNode := visu.CallAccept(FNode.Value); if Assigned(FNode.Lookback) then FLookbackNode := visu.CallAccept(FNode.Lookback) 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; { TSeriesLengthNodeHandler } procedure TSeriesLengthNodeHandler.BuildUI(OwnerNode: TAstViewNode); var titleLabel: TTextNode; begin OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Length of: ' + FNode.Series.Name); titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold]; end; function TSeriesLengthNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.SeriesLength(FNode.Identity, FNode.Series, FNode.StaticType); end; end.