unit Myc.Fmx.AstEditor.Handlers; interface uses System.SysUtils, System.Classes, System.UITypes, System.Generics.Collections, System.Types, 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.Core; type // --- Basic Handlers --- TConstantNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TIdentifierNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TKeywordNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TNopNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; // --- Logic & Control Flow --- TBlockExpressionNodeHandler = class(TBaseNodeHandler) private FChildNodes: TList; public constructor Create(const ANode: IBlockExpressionNode); destructor Destroy; override; procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TIfExpressionNodeHandler = class(TBaseNodeHandler) private FConditionNode: TAuraNode; FThenNode: TAuraNode; FElseNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TTernaryExpressionNodeHandler = class(TBaseNodeHandler) private FConditionNode: TAuraNode; FThenNode: TAuraNode; FElseNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; // --- Functions & Calls --- TLambdaExpressionNodeHandler = class(TBaseNodeHandler) private FBodyNode: TAuraNode; FParamLabels: TList; public constructor Create(const ANode: ILambdaExpressionNode); destructor Destroy; override; procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TFunctionCallNodeHandler = class(TBaseNodeHandler) private FCalleeNode: TAuraNode; FArgumentNodes: TList; public constructor Create(const ANode: IFunctionCallNode); destructor Destroy; override; procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TMacroExpansionNodeHandler = class(TBaseNodeHandler) private FExpandedBodyNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TRecurNodeHandler = class(TBaseNodeHandler) private FArgumentNodes: TList; public constructor Create(const ANode: IRecurNode); destructor Destroy; override; procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; // --- Declarations & Assignments --- TVariableDeclarationNodeHandler = class(TBaseNodeHandler) private FTargetNode: TAuraNode; FInitializerNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TAssignmentNodeHandler = class(TBaseNodeHandler) private FTargetNode: TAuraNode; FValueNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TMacroDefinitionNodeHandler = class(TBaseNodeHandler) private FBodyNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; // --- Metaprogramming --- TQuasiquoteNodeHandler = class(TBaseNodeHandler) private FExpressionNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TUnquoteNodeHandler = class(TBaseNodeHandler) private FExpressionNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TUnquoteSplicingNodeHandler = class(TBaseNodeHandler) private FExpressionNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; // --- Data Access & Structures --- TIndexerNodeHandler = class(TBaseNodeHandler) private FBaseNode: TAuraNode; FIndexNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TMemberAccessNodeHandler = class(TBaseNodeHandler) private FBaseNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TRecordLiteralNodeHandler = class(TBaseNodeHandler) private FFieldNodes: TDictionary; public constructor Create(const ANode: IRecordLiteralNode); destructor Destroy; override; procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; // --- Series Operations --- TCreateSeriesNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TAddSeriesItemNodeHandler = class(TBaseNodeHandler) private FValueNode: TAuraNode; FLookbackNode: TAuraNode; public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; TSeriesLengthNodeHandler = class(TBaseNodeHandler) public procedure BuildUI(OwnerNode: TAuraNode); override; function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override; end; implementation { TConstantNodeHandler } procedure TConstantNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.Constant(FNode.Identity.AsConstant, FNode.StaticType); end; { TIdentifierNodeHandler } procedure TIdentifierNodeHandler.BuildUI(OwnerNode: TAuraNode); begin OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.AddLabel(OwnerNode, FNode.Name); finally OwnerNode.EndUpdate; end; end; function TIdentifierNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode; begin Result := TAst.Identifier(FNode.Identity.AsNamed, FNode.Address, FNode.StaticType); end; { TKeywordNodeHandler } procedure TKeywordNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.Keyword(FNode.Identity.AsKeyword); end; { TNopNodeHandler } procedure TNopNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): IAstNode; begin Result := FNode; end; { TBlockExpressionNodeHandler } constructor TBlockExpressionNodeHandler.Create(const ANode: IBlockExpressionNode); begin inherited Create(ANode); FChildNodes := TList.Create; end; destructor TBlockExpressionNodeHandler.Destroy; begin FChildNodes.Free; inherited; end; procedure TBlockExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode); var visu: IAstVisualizer; childNode: TAuraNode; expr: IAstNode; titleLabel: TLabel; i: Integer; returnContainer: TAutoFitControl; visuReturn: IAstVisualizer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := True; OwnerNode.Orientation := loVertical; OwnerNode.Alignment := laFlush; for i := 0 to High(FNode.Expressions) do begin expr := FNode.Expressions[i]; if i = High(FNode.Expressions) then begin returnContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter); titleLabel := OwnerNode.AddLabel(returnContainer, 'return'); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; visuReturn := OwnerNode.Visualizer.Clone(returnContainer, OwnerNode.Visualizer.ExprDepth + 1); childNode := visuReturn.CallAccept(expr); FChildNodes.Add(childNode); end else begin childNode := visu.CallAccept(expr); FChildNodes.Add(childNode); end; end; finally OwnerNode.EndUpdate; end; end; function TBlockExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode; var exprs: TArray; childNode: TAuraNode; i: Integer; begin SetLength(exprs, FChildNodes.Count); for i := 0 to FChildNodes.Count - 1 do begin childNode := FChildNodes[i]; if Assigned(childNode) then exprs[i] := childNode.CreateAst else exprs[i] := TAst.Nop; end; Result := TAst.Block(FNode.Identity, exprs, FNode.StaticType); end; { TIfExpressionNodeHandler } procedure TIfExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): 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: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.TernaryExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, FElseNode.CreateAst, FNode.StaticType); end; { TLambdaExpressionNodeHandler } constructor TLambdaExpressionNodeHandler.Create(const ANode: ILambdaExpressionNode); begin inherited Create(ANode); FParamLabels := TList.Create; end; destructor TLambdaExpressionNodeHandler.Destroy; begin FParamLabels.Free; inherited; end; procedure TLambdaExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode); var visu: IAstVisualizer; titleContainer: TAutoFitControl; paramLabel: TLabel; i: Integer; 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); paramLabel := OwnerNode.AddLabel(titleContainer, 'fn'); paramLabel.Font.Style := paramLabel.Font.Style + [TFontStyle.fsBold]; FParamLabels.Add(paramLabel); paramLabel := OwnerNode.AddLabel(titleContainer, '('); FParamLabels.Add(paramLabel); for i := 0 to High(FNode.Parameters) do begin paramLabel := OwnerNode.AddLabel(titleContainer, FNode.Parameters[i].Name); FParamLabels.Add(paramLabel); if i < High(FNode.Parameters) then begin paramLabel := OwnerNode.AddLabel(titleContainer, ','); FParamLabels.Add(paramLabel); end; end; paramLabel := OwnerNode.AddLabel(titleContainer, ')'); FParamLabels.Add(paramLabel); FBodyNode := visu.CallAccept(FNode.Body); FBodyNode.Frameless := False; finally OwnerNode.EndUpdate; end; end; function TLambdaExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode; begin Result := TAst.LambdaExpr( FNode.Identity, FNode.Parameters, FBodyNode.CreateAst, FNode.Layout, FNode.Descriptor, FNode.Upvalues, FNode.HasNestedLambdas, FNode.IsPure, FNode.StaticType ); end; { TFunctionCallNodeHandler } constructor TFunctionCallNodeHandler.Create(const ANode: IFunctionCallNode); begin inherited Create(ANode); FArgumentNodes := TList.Create; end; destructor TFunctionCallNodeHandler.Destroy; begin FArgumentNodes.Free; inherited; end; procedure TFunctionCallNodeHandler.BuildUI(OwnerNode: TAuraNode); var visu: IAstVisualizer; i: Integer; argNode: TAuraNode; 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); if Length(FNode.Arguments) > 0 then begin OwnerNode.AddLabel(OwnerNode, '('); for i := 0 to High(FNode.Arguments) do begin argNode := visu.CallAccept(FNode.Arguments[i]); FArgumentNodes.Add(argNode); if i < High(FNode.Arguments) then OwnerNode.AddLabel(OwnerNode, ','); end; OwnerNode.AddLabel(OwnerNode, ')'); end; finally OwnerNode.EndUpdate; end; end; function TFunctionCallNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode; var args: TArray; i: Integer; begin SetLength(args, FArgumentNodes.Count); for i := 0 to FArgumentNodes.Count - 1 do args[i] := FArgumentNodes[i].CreateAst; Result := TAst.FunctionCall( FNode.Identity, FCalleeNode.CreateAst, args, FNode.StaticType, FNode.IsTailCall, FNode.StaticTarget, FNode.IsTargetPure ); end; { TMacroExpansionNodeHandler } procedure TMacroExpansionNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.MacroExpansionNode(FNode.Identity, FNode.CallNode, FExpandedBodyNode.CreateAst.AsTypedNode); end; { TRecurNodeHandler } constructor TRecurNodeHandler.Create(const ANode: IRecurNode); begin inherited Create(ANode); FArgumentNodes := TList.Create; end; destructor TRecurNodeHandler.Destroy; begin FArgumentNodes.Free; inherited; end; procedure TRecurNodeHandler.BuildUI(OwnerNode: TAuraNode); var visu: IAstVisualizer; i: Integer; argNode: TAuraNode; 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]; OwnerNode.AddLabel(OwnerNode, '('); for i := 0 to High(FNode.Arguments) do begin argNode := visu.CallAccept(FNode.Arguments[i]); FArgumentNodes.Add(argNode); if i < High(FNode.Arguments) then OwnerNode.AddLabel(OwnerNode, ','); end; OwnerNode.AddLabel(OwnerNode, ')'); finally OwnerNode.EndUpdate; end; end; function TRecurNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode; var args: TArray; i: Integer; begin SetLength(args, FArgumentNodes.Count); for i := 0 to FArgumentNodes.Count - 1 do args[i] := FArgumentNodes[i].CreateAst; Result := TAst.Recur(FNode.Identity, args, FNode.StaticType); end; { TVariableDeclarationNodeHandler } procedure TVariableDeclarationNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): 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: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.Assign(FNode.Identity, FTargetNode.CreateAst, FValueNode.CreateAst, FNode.StaticType); end; { TMacroDefinitionNodeHandler } procedure TMacroDefinitionNodeHandler.BuildUI(OwnerNode: TAuraNode); var visu: IAstVisualizer; titleLabel: TLabel; paramStr: string; i: Integer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; paramStr := ''; for i := 0 to High(FNode.Parameters) do begin if i > 0 then paramStr := paramStr + ', '; paramStr := paramStr + FNode.Parameters[i].Name; end; titleLabel := OwnerNode.AddLabel(OwnerNode, 'Macro Def: ' + FNode.Name.Name + ' (' + paramStr + ')'); titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; FBodyNode := visu.CallAccept(FNode.Body); finally OwnerNode.EndUpdate; end; end; function TMacroDefinitionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode; begin Result := TAst.MacroDef(FNode.Identity, FNode.Name, FNode.Parameters, FBodyNode.CreateAst); end; { TQuasiquoteNodeHandler } procedure TQuasiquoteNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.Quasiquote(FNode.Identity, FExpressionNode.CreateAst); end; { TUnquoteNodeHandler } procedure TUnquoteNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.Unquote(FNode.Identity, FExpressionNode.CreateAst); end; { TUnquoteSplicingNodeHandler } procedure TUnquoteSplicingNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.UnquoteSplicing(FNode.Identity, FExpressionNode.CreateAst.AsQuasiquote); end; { TIndexerNodeHandler } procedure TIndexerNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.Indexer(FNode.Identity, FBaseNode.CreateAst, FIndexNode.CreateAst, FNode.StaticType); end; { TMemberAccessNodeHandler } procedure TMemberAccessNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): 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 } constructor TRecordLiteralNodeHandler.Create(const ANode: IRecordLiteralNode); begin inherited Create(ANode); FFieldNodes := TDictionary.Create; end; destructor TRecordLiteralNodeHandler.Destroy; begin FFieldNodes.Free; inherited; end; procedure TRecordLiteralNodeHandler.BuildUI(OwnerNode: TAuraNode); var field: TRecordFieldLiteral; fieldContainer: TAutoFitControl; valueNode: TAuraNode; keyLabel: TLabel; begin OwnerNode.BeginUpdate; try OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; OwnerNode.Alignment := laFlush; if Length(FNode.Fields) = 0 then begin OwnerNode.AddLabel(OwnerNode, '{}'); end else begin for field in FNode.Fields do begin fieldContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter); keyLabel := OwnerNode.AddLabel(fieldContainer, ':' + field.Key.Value.Name); keyLabel.Font.Style := keyLabel.Font.Style + [TFontStyle.fsBold]; keyLabel.StyledSettings := keyLabel.StyledSettings - [TStyledSetting.FontColor]; keyLabel.FontColor := TAlphaColors.Mediumvioletred; valueNode := OwnerNode.Visualizer.Clone(fieldContainer, OwnerNode.Visualizer.ExprDepth + 1).CallAccept(field.Value); FFieldNodes.Add(field.Key.Value, valueNode); end; end; finally OwnerNode.EndUpdate; end; end; function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode; var fields: TArray; i: Integer; valueNode: TAuraNode; pair: TPair; begin SetLength(fields, FFieldNodes.Count); i := 0; for pair in FFieldNodes do begin valueNode := pair.Value; fields[i] := TRecordFieldLiteral.Create(TAst.Keyword(pair.Key.Name), valueNode.CreateAst); inc(i); end; Result := TAst.RecordLiteral(FNode.Identity, fields, FNode.ScalarDefinition, FNode.GenericDefinition, FNode.StaticType); end; { TCreateSeriesNodeHandler } procedure TCreateSeriesNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.CreateSeries(FNode.Identity.AsDefinition, FNode.StaticType); end; { TAddSeriesItemNodeHandler } procedure TAddSeriesItemNodeHandler.BuildUI(OwnerNode: TAuraNode); 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: TAuraNode): 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: TAuraNode); 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: TAuraNode): IAstNode; begin Result := TAst.SeriesLength(FNode.Identity, FNode.Series, FNode.StaticType); end; end.