unit Myc.Fmx.AstEditor.Handlers; interface uses System.SysUtils, System.Classes, System.Types, System.UITypes, System.Generics.Collections, FMX.Types, FMX.Controls, FMX.StdCtrls, FMX.Graphics, Myc.Data.Value, Myc.Data.Keyword, Myc.Ast, Myc.Ast.Nodes, Myc.Ast.Identities, Myc.Fmx.AstEditor.Layout, Myc.Fmx.AstEditor; type // --- Abstract List Base --- // Now implements IReorderable to support drag & drop reordering TNodeListHandler = class(TBaseNodeHandler>, IReorderable) protected FChildNodes: TList; function GetOrientation: TLayoutOrientation; virtual; abstract; function GetAlignment: TLayoutAlignment; virtual; public constructor Create(const ANode: INodeList); destructor Destroy; override; procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; abstract; // IReorderable Implementation function CanDrag(Child: TControl): Boolean; procedure MoveChild(SourceIndex, TargetIndex: Integer); end; // --- Concrete List Handlers --- TParameterListHandler = class(TNodeListHandler) protected function GetOrientation: TLayoutOrientation; override; public function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TArgumentListHandler = class(TNodeListHandler) protected function GetOrientation: TLayoutOrientation; override; public function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TExpressionListHandler = class(TNodeListHandler) protected function GetOrientation: TLayoutOrientation; override; function GetAlignment: TLayoutAlignment; override; public function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TRecordFieldListHandler = class(TNodeListHandler) protected function GetOrientation: TLayoutOrientation; override; function GetAlignment: TLayoutAlignment; override; public function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; // --- Node Handlers --- TRecordFieldHandler = class(TBaseNodeHandler) private FKeyLabel: TLabel; FValueNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TConstantNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TIdentifierNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TKeywordNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TNopNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; // --- Logic & Control Flow --- TBlockExpressionNodeHandler = class(TBaseNodeHandler) private FExpressionsNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TIfExpressionNodeHandler = class(TBaseNodeHandler) private FConditionNode: TAstViewNode; FThenNode: TAstViewNode; FElseNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TTernaryExpressionNodeHandler = class(TBaseNodeHandler) private FConditionNode: TAstViewNode; FThenNode: TAstViewNode; FElseNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; // --- Functions & Calls --- TLambdaExpressionNodeHandler = class(TBaseNodeHandler) private FParamsNode: TAstViewNode; FBodyNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TFunctionCallNodeHandler = class(TBaseNodeHandler) private FCalleeNode: TAstViewNode; FArgumentsNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TMacroExpansionNodeHandler = class(TBaseNodeHandler) private FExpandedBodyNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TRecurNodeHandler = class(TBaseNodeHandler) private FArgumentsNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; // --- 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; TMacroDefinitionNodeHandler = class(TBaseNodeHandler) private FParamsNode: TAstViewNode; FBodyNode: 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; 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 { TNodeListHandler } constructor TNodeListHandler.Create(const ANode: INodeList); begin inherited Create(ANode); FChildNodes := TList.Create; end; destructor TNodeListHandler.Destroy; begin FChildNodes.Free; inherited; end; function TNodeListHandler.GetAlignment: TLayoutAlignment; begin Result := TLayoutAlignment.laCenter; end; procedure TNodeListHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; i: Integer; childView: TAstViewNode; openTok, closeTok, sep: string; listId: IListIdentity; begin if (FNode.Identity <> nil) and (FNode.Identity.Kind = ikList) then begin listId := FNode.Identity.AsList; openTok := listId.OpenToken; closeTok := listId.CloseToken; sep := listId.Separator; end else begin openTok := ''; closeTok := ''; sep := ' '; end; visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth); OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := GetOrientation; OwnerNode.Alignment := GetAlignment; if openTok <> '' then OwnerNode.AddLabel(OwnerNode, openTok); for i := 0 to FNode.Count - 1 do begin childView := visu.CallAccept(FNode[i]); FChildNodes.Add(childView); if (i < FNode.Count - 1) and (sep <> '') and (sep <> ' ') then OwnerNode.AddLabel(OwnerNode, sep); end; if closeTok <> '' then OwnerNode.AddLabel(OwnerNode, closeTok); if FNode.Count = 0 then begin if (openTok = '') and (closeTok = '') then begin var lbl := OwnerNode.AddLabel(OwnerNode, 'ø'); lbl.Opacity := 0.5; end; end; finally OwnerNode.EndUpdate; end; end; // IReorderable Implementation function TNodeListHandler.CanDrag(Child: TControl): Boolean; begin // Allow dragging only if the child is one of our managed ViewNodes Result := (Child is TAstViewNode) and FChildNodes.Contains(TAstViewNode(Child)); end; procedure TNodeListHandler.MoveChild(SourceIndex, TargetIndex: Integer); var item: TAstViewNode; begin if (SourceIndex < 0) or (SourceIndex >= FChildNodes.Count) then Exit; if (TargetIndex < 0) or (TargetIndex > FChildNodes.Count) then Exit; // Adjust target index if moving downwards (since removing source shifts indices) if SourceIndex < TargetIndex then Dec(TargetIndex); if SourceIndex = TargetIndex then Exit; item := FChildNodes[SourceIndex]; FChildNodes.Delete(SourceIndex); FChildNodes.Insert(TargetIndex, item); // The visual order update will happen upon the next ReconstructAst -> Compile -> BuildUI cycle // triggered by the controller. end; { TParameterListHandler } function TParameterListHandler.GetOrientation: TLayoutOrientation; begin Result := loHorizontal; end; function TParameterListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; var arr: TArray; i: Integer; begin SetLength(arr, FChildNodes.Count); for i := 0 to FChildNodes.Count - 1 do arr[i] := FChildNodes[i].CreateAst.AsIdentifier; Result := TParameterList.Create(arr, FNode.Identity); end; { TArgumentListHandler } function TArgumentListHandler.GetOrientation: TLayoutOrientation; begin Result := loHorizontal; end; function TArgumentListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; var arr: TArray; i: Integer; begin SetLength(arr, FChildNodes.Count); for i := 0 to FChildNodes.Count - 1 do arr[i] := FChildNodes[i].CreateAst; Result := TArgumentList.Create(arr, FNode.Identity); end; { TExpressionListHandler } function TExpressionListHandler.GetOrientation: TLayoutOrientation; begin Result := loVertical; end; function TExpressionListHandler.GetAlignment: TLayoutAlignment; begin Result := laFlush; end; function TExpressionListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; var arr: TArray; i: Integer; begin SetLength(arr, FChildNodes.Count); for i := 0 to FChildNodes.Count - 1 do arr[i] := FChildNodes[i].CreateAst; Result := TExpressionList.Create(arr, FNode.Identity); end; { TRecordFieldListHandler } function TRecordFieldListHandler.GetOrientation: TLayoutOrientation; begin Result := loVertical; end; function TRecordFieldListHandler.GetAlignment: TLayoutAlignment; begin Result := laFlush; end; function TRecordFieldListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; var arr: TArray; i: Integer; begin SetLength(arr, FChildNodes.Count); for i := 0 to FChildNodes.Count - 1 do arr[i] := FChildNodes[i].CreateAst.AsRecordField; Result := TRecordFieldList.Create(arr, FNode.Identity); end; { TRecordFieldHandler } procedure TRecordFieldHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth); OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; OwnerNode.Alignment := laCenter; FKeyLabel := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Key.Value.Name); FKeyLabel.Font.Style := FKeyLabel.Font.Style + [TFontStyle.fsBold]; FKeyLabel.StyledSettings := FKeyLabel.StyledSettings - [TStyledSetting.FontColor]; FKeyLabel.FontColor := TAlphaColors.Mediumvioletred; FValueNode := visu.CallAccept(FNode.Value); finally OwnerNode.EndUpdate; end; end; function TRecordFieldHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin // Updated to use new Factory Overload to preserve Identity Result := TAst.RecordField(FNode.Identity, FNode.Key, FValueNode.CreateAst); end; { TConstantNodeHandler } procedure TConstantNodeHandler.BuildUI(OwnerNode: TAstViewNode); var valueStr: string; isConcise: Boolean; titleLabel: TLabel; valueLabel: TLabel; begin OwnerNode.BeginUpdate; try valueStr := FNode.Value.ToString; isConcise := ((FNode.Value.Kind = TDataValueKind.vkScalar) or (Pos(sLineBreak, valueStr) = 0)) and (Length(valueStr) < 40); if isConcise then begin OwnerNode.Frameless := True; OwnerNode.AddLabel(OwnerNode, valueStr); end else begin OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Const'); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; valueLabel := OwnerNode.AddLabel(OwnerNode, valueStr); valueLabel.AutoSize := False; valueLabel.WordWrap := True; end; finally OwnerNode.EndUpdate; end; end; function TConstantNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Constant(FNode.Identity.AsConstant, FNode.StaticType); end; { TIdentifierNodeHandler } procedure TIdentifierNodeHandler.BuildUI(OwnerNode: TAstViewNode); begin OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.AddLabel(OwnerNode, FNode.Name); finally OwnerNode.EndUpdate; end; end; function TIdentifierNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Identifier(FNode.Identity.AsNamed, FNode.Address, FNode.StaticType); end; { TKeywordNodeHandler } procedure TKeywordNodeHandler.BuildUI(OwnerNode: TAstViewNode); var lbl: TLabel; begin OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; lbl := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Value.Name); lbl.StyledSettings := lbl.StyledSettings - [TStyledSetting.FontColor]; lbl.FontColor := TAlphaColors.Mediumvioletred; finally OwnerNode.EndUpdate; end; end; function TKeywordNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Keyword(FNode.Identity.AsKeyword); end; { TNopNodeHandler } procedure TNopNodeHandler.BuildUI(OwnerNode: TAstViewNode); var lbl: TLabel; begin OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Alignment := TLayoutAlignment.laCenter; OwnerNode.Orientation := TLayoutOrientation.loHorizontal; lbl := OwnerNode.AddLabel(OwnerNode, '...'); lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold]; lbl.Margins.Rect := TRectF.Create(8, 4, 8, 4); finally OwnerNode.EndUpdate; end; end; function TNopNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := FNode; end; { TBlockExpressionNodeHandler } procedure TBlockExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleLabel: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; OwnerNode.Alignment := laFlush; titleLabel := OwnerNode.AddLabel(OwnerNode, 'do'); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; FExpressionsNode := visu.CallAccept(FNode.Expressions); FExpressionsNode.Frameless := True; finally OwnerNode.EndUpdate; end; end; function TBlockExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Block(FNode.Identity, FExpressionsNode.CreateAst.AsExpressionList, FNode.StaticType); end; { TIfExpressionNodeHandler } procedure TIfExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode); begin OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; OwnerNode.Alignment := laFlush; FConditionNode := OwnerNode.AddExpr(OwnerNode, 'if', FNode.Condition); FThenNode := OwnerNode.AddExpr(OwnerNode, 'then', FNode.ThenBranch); if Assigned(FNode.ElseBranch) then FElseNode := OwnerNode.AddExpr(OwnerNode, 'else', FNode.ElseBranch); finally OwnerNode.EndUpdate; end; end; function TIfExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; var elseAst: IAstNode; begin if Assigned(FElseNode) then elseAst := FElseNode.CreateAst else elseAst := nil; Result := TAst.IfExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, elseAst, FNode.StaticType); end; { TTernaryExpressionNodeHandler } procedure TTernaryExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; FConditionNode := visu.CallAccept(FNode.Condition); OwnerNode.AddLabel(OwnerNode, '?'); FThenNode := visu.CallAccept(FNode.ThenBranch); OwnerNode.AddLabel(OwnerNode, ':'); FElseNode := visu.CallAccept(FNode.ElseBranch); finally OwnerNode.EndUpdate; end; end; function TTernaryExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.TernaryExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, FElseNode.CreateAst, FNode.StaticType); end; { TLambdaExpressionNodeHandler } procedure TLambdaExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleContainer: TAutoFitControl; lbl: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, 0); OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; OwnerNode.Alignment := laFlush; OwnerNode.BackgroundColor := $090000ff; titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter); lbl := OwnerNode.AddLabel(titleContainer, 'fn'); lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold]; // Parameters: Delegate to List Handler var paramVisu := visu.Clone(titleContainer, 0); FParamsNode := paramVisu.CallAccept(FNode.Parameters); // Body FBodyNode := visu.CallAccept(FNode.Body); FBodyNode.Frameless := False; finally OwnerNode.EndUpdate; end; end; function TLambdaExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.LambdaExpr( FNode.Identity, FParamsNode.CreateAst.AsParameterList, FBodyNode.CreateAst, FNode.Layout, FNode.Descriptor, FNode.Upvalues, FNode.HasNestedLambdas, FNode.IsPure, FNode.StaticType ); end; { TFunctionCallNodeHandler } procedure TFunctionCallNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; callLabel: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; callLabel := OwnerNode.AddLabel(OwnerNode, 'call '); callLabel.Font.Style := callLabel.Font.Style + [TFontStyle.fsBold]; FCalleeNode := visu.CallAccept(FNode.Callee); FArgumentsNode := visu.CallAccept(FNode.Arguments); finally OwnerNode.EndUpdate; end; end; function TFunctionCallNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.FunctionCall( FNode.Identity, FCalleeNode.CreateAst, FArgumentsNode.CreateAst.AsArgumentList, FNode.StaticType, FNode.IsTailCall, FNode.StaticTarget, FNode.IsTargetPure ); end; { TMacroExpansionNodeHandler } procedure TMacroExpansionNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleLabel: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Macro Expansion'); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; FExpandedBodyNode := visu.CallAccept(FNode.ExpandedBody); finally OwnerNode.EndUpdate; end; end; function TMacroExpansionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.MacroExpansionNode(FNode.Identity, FNode.CallNode, FExpandedBodyNode.CreateAst.AsTypedNode); end; { TRecurNodeHandler } procedure TRecurNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleLabel: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; titleLabel := OwnerNode.AddLabel(OwnerNode, 'recur'); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; FArgumentsNode := visu.CallAccept(FNode.Arguments); finally OwnerNode.EndUpdate; end; end; function TRecurNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Recur(FNode.Identity, FArgumentsNode.CreateAst.AsArgumentList, FNode.StaticType); end; { TVariableDeclarationNodeHandler } procedure TVariableDeclarationNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; varLabel: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; varLabel := OwnerNode.AddLabel(OwnerNode, 'var'); varLabel.Font.Style := varLabel.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; finally OwnerNode.EndUpdate; end; 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.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; FTargetNode := visu.CallAccept(FNode.Target); OwnerNode.AddLabel(OwnerNode, ':='); FValueNode := visu.CallAccept(FNode.Value); finally OwnerNode.EndUpdate; end; end; function TAssignmentNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Assign(FNode.Identity, FTargetNode.CreateAst, FValueNode.CreateAst, FNode.StaticType); end; { TMacroDefinitionNodeHandler } procedure TMacroDefinitionNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleLabel: TLabel; titleContainer: TAutoFitControl; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter); titleLabel := OwnerNode.AddLabel(titleContainer, 'Macro Def: ' + FNode.Name.Name); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; // Parameters List var paramVisu := visu.Clone(titleContainer, visu.ExprDepth); FParamsNode := paramVisu.CallAccept(FNode.Parameters); FBodyNode := visu.CallAccept(FNode.Body); finally OwnerNode.EndUpdate; end; end; function TMacroDefinitionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.MacroDef(FNode.Identity, FNode.Name, FParamsNode.CreateAst.AsParameterList, FBodyNode.CreateAst); end; { TQuasiquoteNodeHandler } procedure TQuasiquoteNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; titleLabel: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Quasiquote'); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; FExpressionNode := visu.CallAccept(FNode.Expression); finally OwnerNode.EndUpdate; end; 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: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; leftBracket := OwnerNode.AddLabel(OwnerNode, '<'); leftBracket.Padding.Right := 0; leftBracket.Margins.Right := 0; FExpressionNode := visu.CallAccept(FNode.Expression); rightBracket := OwnerNode.AddLabel(OwnerNode, '>'); rightBracket.Padding.Left := 0; rightBracket.Margins.Left := 0; finally OwnerNode.EndUpdate; end; 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: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Unquote-Splicing'); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; FExpressionNode := visu.CallAccept(FNode.Expression); finally OwnerNode.EndUpdate; end; 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.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; FBaseNode := visu.CallAccept(FNode.Base); OwnerNode.AddLabel(OwnerNode, '['); FIndexNode := visu.CallAccept(FNode.Index); OwnerNode.AddLabel(OwnerNode, ']'); finally OwnerNode.EndUpdate; end; 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.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; FBaseNode := visu.CallAccept(FNode.Base); OwnerNode.AddLabel(OwnerNode, '.'); OwnerNode.AddLabel(OwnerNode, FNode.Member.Value.Name); finally OwnerNode.EndUpdate; end; end; function TMemberAccessNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin // Reuse Identifier, Reuse Member Keyword (via TAst.Keyword with Identity) Result := TAst.MemberAccess(FNode.Identity, FBaseNode.CreateAst, TAst.Keyword(FNode.Member.Identity.AsKeyword), FNode.StaticType); end; { TRecordLiteralNodeHandler } procedure TRecordLiteralNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; OwnerNode.Alignment := laFlush; // Delegate to RecordFieldList FFieldsNode := visu.CallAccept(FNode.Fields); finally OwnerNode.EndUpdate; end; 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: TLabel; begin OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Create Series: ' + FNode.Definition); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; finally OwnerNode.EndUpdate; end; 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: TLabel; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Add Item to: ' + FNode.Series.Name); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; FValueNode := visu.CallAccept(FNode.Value); if Assigned(FNode.Lookback) then FLookbackNode := visu.CallAccept(FNode.Lookback) else FLookbackNode := nil; finally OwnerNode.EndUpdate; end; 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: TLabel; begin OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Length of: ' + FNode.Series.Name); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; finally OwnerNode.EndUpdate; end; end; function TSeriesLengthNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.SeriesLength(FNode.Identity, FNode.Series, FNode.StaticType); end; end.