unit Myc.Ast; interface uses System.SysUtils, Myc.Data.Scalar, Myc.Ast.Nodes; type // Record acting as a namespace for the factory functions. TAst = record class function Constant(AValue: TScalar): IConstantNode; static; class function Identifier(AName: string): IIdentifierNode; static; class function BinaryExpr( ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode ): IBinaryExpressionNode; static; class function UnaryExpr(const AOperator: TUnaryOperator; const ARight: IExpressionNode): IUnaryExpressionNode; static; class function IfExpr( const ACondition: IExpressionNode; const AThenBranch, AElseBranch: IExpressionNode ): IIfExpressionNode; static; class function TernaryExpr( const ACondition: IExpressionNode; const AThenBranch, AElseBranch: IExpressionNode ): ITernaryExpressionNode; static; class function LambdaExpr(const AParameters: TArray; const ABody: IExpressionNode): ILambdaExpressionNode; static; class function FunctionCall(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode): IFunctionCallNode; static; class function Block(const AExpressions: array of IExpressionNode): IBlockExpressionNode; static; class function VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode): IVariableDeclarationNode; static; class function Assign(const AIdentifier: IIdentifierNode; const AValue: IExpressionNode): IAssignmentNode; static; class function AssignResult(const AValue: IExpressionNode): IAssignmentNode; static; class function Indexer(const ABase: IExpressionNode; const AIndex: IExpressionNode): IIndexerNode; static; class function MemberAccess(const ABase: IExpressionNode; const AMember: IIdentifierNode): IMemberAccessNode; static; class function CreateSeries(const ADefinition: String): ICreateSeriesNode; static; class function AddSeriesItem( const ASeries: IIdentifierNode; const AValue: IExpressionNode; const ALookback: IExpressionNode = nil ): IAddSeriesItemNode; static; // Added the new factory function for SeriesLength class function SeriesLength(const ASeries: IIdentifierNode): ISeriesLengthNode; static; end; implementation uses System.Classes, System.Generics.Collections; type { TAstNode } // Common base class for AST nodes to reduce boilerplate. TAstNode = class(TInterfacedObject, IExpressionNode) public function Accept(const Visitor: IAstVisitor): TAstValue; virtual; abstract; end; { TConstantNode } TConstantNode = class(TAstNode, IConstantNode) private FValue: TScalar; function GetValue: TScalar; public constructor Create(AValue: TScalar); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TIdentifierNode } TIdentifierNode = class(TAstNode, IIdentifierNode) private FName: string; function GetName: string; public constructor Create(AName: string); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TBinaryExpressionNode } TBinaryExpressionNode = class(TAstNode, IBinaryExpressionNode) private FLeft: IExpressionNode; FOperator: TBinaryOperator; FRight: IExpressionNode; function GetLeft: IExpressionNode; function GetOperator: TBinaryOperator; function GetRight: IExpressionNode; public constructor Create(ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TUnaryExpressionNode } TUnaryExpressionNode = class(TAstNode, IUnaryExpressionNode) private FOperator: TUnaryOperator; FRight: IExpressionNode; function GetOperator: TUnaryOperator; function GetRight: IExpressionNode; public constructor Create(const AOperator: TUnaryOperator; const ARight: IExpressionNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TIfExpressionNode } TIfExpressionNode = class(TAstNode, IIfExpressionNode) private FCondition: IExpressionNode; FThenBranch: IExpressionNode; FElseBranch: IExpressionNode; function GetCondition: IExpressionNode; function GetThenBranch: IExpressionNode; function GetElseBranch: IExpressionNode; public constructor Create(const ACondition, AThenBranch, AElseBranch: IExpressionNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TTernaryExpressionNode } TTernaryExpressionNode = class(TAstNode, ITernaryExpressionNode) private FCondition: IExpressionNode; FThenBranch: IExpressionNode; FElseBranch: IExpressionNode; function GetCondition: IExpressionNode; function GetThenBranch: IExpressionNode; function GetElseBranch: IExpressionNode; public constructor Create(const ACondition, AThenBranch, AElseBranch: IExpressionNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TLambdaExpressionNode } TLambdaExpressionNode = class(TAstNode, ILambdaExpressionNode) private FParameters: TArray; FBody: IExpressionNode; function GetParameters: TArray; function GetBody: IExpressionNode; public constructor Create(const AParameters: TArray; const ABody: IExpressionNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TFunctionCallNode } TFunctionCallNode = class(TAstNode, IFunctionCallNode) private FCallee: IExpressionNode; FArguments: TList; function GetCallee: IExpressionNode; function GetArguments: TList; public constructor Create(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode); destructor Destroy; override; function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TBlockExpressionNode } TBlockExpressionNode = class(TAstNode, IBlockExpressionNode) private FExpressions: TList; function GetExpressions: TList; public constructor Create(const AExpressions: array of IExpressionNode); destructor Destroy; override; function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TVariableDeclarationNode } TVariableDeclarationNode = class(TAstNode, IVariableDeclarationNode) private FIdentifier: IIdentifierNode; FInitializer: IExpressionNode; function GetIdentifier: IIdentifierNode; function GetInitializer: IExpressionNode; public constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TAssignmentNode } TAssignmentNode = class(TAstNode, IAssignmentNode) private FIdentifier: IIdentifierNode; FValue: IExpressionNode; function GetIdentifier: IIdentifierNode; function GetValue: IExpressionNode; public constructor Create(const AIdentifier: IIdentifierNode; const AValue: IExpressionNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TIndexerNode } TIndexerNode = class(TAstNode, IIndexerNode) private FBase: IExpressionNode; FIndex: IExpressionNode; function GetBase: IExpressionNode; function GetIndex: IExpressionNode; public constructor Create(const ABase: IExpressionNode; const AIndex: IExpressionNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TMemberAccessNode } // Concrete implementation for the member access node. TMemberAccessNode = class(TAstNode, IMemberAccessNode) private FBase: IExpressionNode; FMember: IIdentifierNode; function GetBase: IExpressionNode; function GetMember: IIdentifierNode; public constructor Create(const ABase: IExpressionNode; const AMember: IIdentifierNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TCreateSeriesNode } TCreateSeriesNode = class(TAstNode, ICreateSeriesNode) private FDefinition: String; function GetDefinition: String; public constructor Create(const ADefinition: String); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TAddSeriesItemNode } TAddSeriesItemNode = class(TAstNode, IAddSeriesItemNode) private FSeries: IIdentifierNode; FValue: IExpressionNode; FLookback: IExpressionNode; function GetSeries: IIdentifierNode; function GetValue: IExpressionNode; function GetLookback: IExpressionNode; public constructor Create(const ASeries: IIdentifierNode; const AValue: IExpressionNode; const ALookback: IExpressionNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; // Added concrete class for the series length node. { TSeriesLengthNode } TSeriesLengthNode = class(TAstNode, ISeriesLengthNode) private FSeries: IIdentifierNode; function GetSeries: IIdentifierNode; public constructor Create(const ASeries: IIdentifierNode); function Accept(const Visitor: IAstVisitor): TAstValue; override; end; { TConstantNode } constructor TConstantNode.Create(AValue: TScalar); begin inherited Create; FValue := AValue; end; function TConstantNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitConstant(Self); end; function TConstantNode.GetValue: TScalar; begin Result := FValue; end; { TIdentifierNode } constructor TIdentifierNode.Create(AName: string); begin inherited Create; FName := AName; end; function TIdentifierNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitIdentifier(Self); end; function TIdentifierNode.GetName: string; begin Result := FName; end; { TBinaryExpressionNode } constructor TBinaryExpressionNode.Create(ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode); begin inherited Create; FLeft := ALeft; FOperator := AOperator; FRight := ARight; end; function TBinaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitBinaryExpression(Self); end; function TBinaryExpressionNode.GetLeft: IExpressionNode; begin Result := FLeft; end; function TBinaryExpressionNode.GetOperator: TBinaryOperator; begin Result := FOperator; end; function TBinaryExpressionNode.GetRight: IExpressionNode; begin Result := FRight; end; { TUnaryExpressionNode } constructor TUnaryExpressionNode.Create(const AOperator: TUnaryOperator; const ARight: IExpressionNode); begin inherited Create; FOperator := AOperator; FRight := ARight; end; function TUnaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitUnaryExpression(Self); end; function TUnaryExpressionNode.GetOperator: TUnaryOperator; begin Result := FOperator; end; function TUnaryExpressionNode.GetRight: IExpressionNode; begin Result := FRight; end; { TIfExpressionNode } constructor TIfExpressionNode.Create(const ACondition, AThenBranch, AElseBranch: IExpressionNode); begin inherited Create; FCondition := ACondition; FThenBranch := AThenBranch; FElseBranch := AElseBranch; end; function TIfExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitIfExpression(Self); end; function TIfExpressionNode.GetCondition: IExpressionNode; begin Result := FCondition; end; function TIfExpressionNode.GetElseBranch: IExpressionNode; begin Result := FElseBranch; end; function TIfExpressionNode.GetThenBranch: IExpressionNode; begin Result := FThenBranch; end; { TTernaryExpressionNode } constructor TTernaryExpressionNode.Create(const ACondition, AThenBranch, AElseBranch: IExpressionNode); begin inherited Create; FCondition := ACondition; FThenBranch := AThenBranch; FElseBranch := AElseBranch; end; function TTernaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitTernaryExpression(Self); end; function TTernaryExpressionNode.GetCondition: IExpressionNode; begin Result := FCondition; end; function TTernaryExpressionNode.GetElseBranch: IExpressionNode; begin Result := FElseBranch; end; function TTernaryExpressionNode.GetThenBranch: IExpressionNode; begin Result := FThenBranch; end; { TLambdaExpressionNode } constructor TLambdaExpressionNode.Create(const AParameters: TArray; const ABody: IExpressionNode); begin inherited Create; FBody := ABody; FParameters := AParameters; end; function TLambdaExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitLambdaExpression(Self); end; function TLambdaExpressionNode.GetBody: IExpressionNode; begin Result := FBody; end; function TLambdaExpressionNode.GetParameters: TArray; begin Result := FParameters; end; { TFunctionCallNode } constructor TFunctionCallNode.Create(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode); var arg: IExpressionNode; begin inherited Create; FCallee := ACallee; FArguments := TList.Create; for arg in AArguments do FArguments.Add(arg); end; destructor TFunctionCallNode.Destroy; begin FArguments.Free; inherited; end; function TFunctionCallNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitFunctionCall(Self); end; function TFunctionCallNode.GetArguments: TList; begin Result := FArguments; end; function TFunctionCallNode.GetCallee: IExpressionNode; begin Result := FCallee; end; { TBlockExpressionNode } constructor TBlockExpressionNode.Create(const AExpressions: array of IExpressionNode); var expr: IExpressionNode; begin inherited Create; FExpressions := TList.Create; for expr in AExpressions do FExpressions.Add(expr); end; destructor TBlockExpressionNode.Destroy; begin FExpressions.Free; inherited; end; function TBlockExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitBlockExpression(Self); end; function TBlockExpressionNode.GetExpressions: TList; begin Result := FExpressions; end; { TVariableDeclarationNode } constructor TVariableDeclarationNode.Create(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode); begin inherited Create; FIdentifier := AIdentifier; FInitializer := AInitializer; end; function TVariableDeclarationNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitVariableDeclaration(Self); end; function TVariableDeclarationNode.GetIdentifier: IIdentifierNode; begin Result := FIdentifier; end; function TVariableDeclarationNode.GetInitializer: IExpressionNode; begin Result := FInitializer; end; { TAssignmentNode } constructor TAssignmentNode.Create(const AIdentifier: IIdentifierNode; const AValue: IExpressionNode); begin inherited Create; FIdentifier := AIdentifier; FValue := AValue; end; function TAssignmentNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitAssignment(Self); end; function TAssignmentNode.GetIdentifier: IIdentifierNode; begin Result := FIdentifier; end; function TAssignmentNode.GetValue: IExpressionNode; begin Result := FValue; end; { TIndexerNode } constructor TIndexerNode.Create(const ABase, AIndex: IExpressionNode); begin inherited Create; FBase := ABase; FIndex := AIndex; end; function TIndexerNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitIndexer(Self); end; function TIndexerNode.GetBase: IExpressionNode; begin Result := FBase; end; function TIndexerNode.GetIndex: IExpressionNode; begin Result := FIndex; end; { TMemberAccessNode } constructor TMemberAccessNode.Create(const ABase: IExpressionNode; const AMember: IIdentifierNode); begin inherited Create; FBase := ABase; FMember := AMember; end; function TMemberAccessNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitMemberAccess(Self); end; function TMemberAccessNode.GetBase: IExpressionNode; begin Result := FBase; end; function TMemberAccessNode.GetMember: IIdentifierNode; begin Result := FMember; end; { TCreateSeriesNode } constructor TCreateSeriesNode.Create(const ADefinition: String); begin inherited Create; FDefinition := ADefinition; end; function TCreateSeriesNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitCreateSeries(Self); end; function TCreateSeriesNode.GetDefinition: String; begin Result := FDefinition; end; { TAddSeriesItemNode } constructor TAddSeriesItemNode.Create(const ASeries: IIdentifierNode; const AValue, ALookback: IExpressionNode); begin inherited Create; FSeries := ASeries; FValue := AValue; FLookback := ALookback; end; function TAddSeriesItemNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitAddSeriesItem(Self); end; function TAddSeriesItemNode.GetLookback: IExpressionNode; begin Result := FLookback; end; function TAddSeriesItemNode.GetSeries: IIdentifierNode; begin Result := FSeries; end; function TAddSeriesItemNode.GetValue: IExpressionNode; begin Result := FValue; end; { TSeriesLengthNode } constructor TSeriesLengthNode.Create(const ASeries: IIdentifierNode); begin inherited Create; FSeries := ASeries; end; function TSeriesLengthNode.Accept(const Visitor: IAstVisitor): TAstValue; begin Result := Visitor.VisitSeriesLength(Self); end; function TSeriesLengthNode.GetSeries: IIdentifierNode; begin Result := FSeries; end; { TAst } class function TAst.AddSeriesItem( const ASeries: IIdentifierNode; const AValue: IExpressionNode; const ALookback: IExpressionNode ): IAddSeriesItemNode; begin Result := TAddSeriesItemNode.Create(ASeries, AValue, ALookback); end; class function TAst.Assign(const AIdentifier: IIdentifierNode; const AValue: IExpressionNode): IAssignmentNode; begin Result := TAssignmentNode.Create(AIdentifier, AValue); end; class function TAst.AssignResult(const AValue: IExpressionNode): IAssignmentNode; begin Result := Assign(TAst.Identifier('Result'), AValue); end; class function TAst.Block(const AExpressions: array of IExpressionNode): IBlockExpressionNode; begin Result := TBlockExpressionNode.Create(AExpressions); end; class function TAst.Constant(AValue: TScalar): IConstantNode; begin Result := TConstantNode.Create(AValue); end; class function TAst.CreateSeries(const ADefinition: String): ICreateSeriesNode; begin Result := TCreateSeriesNode.Create(ADefinition); end; class function TAst.BinaryExpr(ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode): IBinaryExpressionNode; begin Result := TBinaryExpressionNode.Create(ALeft, AOperator, ARight); end; class function TAst.FunctionCall(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode): IFunctionCallNode; begin Result := TFunctionCallNode.Create(ACallee, AArguments); end; class function TAst.Identifier(AName: string): IIdentifierNode; begin Result := TIdentifierNode.Create(AName); end; class function TAst.IfExpr(const ACondition: IExpressionNode; const AThenBranch, AElseBranch: IExpressionNode): IIfExpressionNode; begin Result := TIfExpressionNode.Create(ACondition, AThenBranch, AElseBranch); end; class function TAst.Indexer(const ABase, AIndex: IExpressionNode): IIndexerNode; begin Result := TIndexerNode.Create(ABase, AIndex); end; class function TAst.MemberAccess(const ABase: IExpressionNode; const AMember: IIdentifierNode): IMemberAccessNode; begin Result := TMemberAccessNode.Create(ABase, AMember); end; class function TAst.SeriesLength(const ASeries: IIdentifierNode): ISeriesLengthNode; begin Result := TSeriesLengthNode.Create(ASeries); end; class function TAst.TernaryExpr(const ACondition: IExpressionNode; const AThenBranch, AElseBranch: IExpressionNode): ITernaryExpressionNode; begin Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch); end; class function TAst.LambdaExpr(const AParameters: TArray; const ABody: IExpressionNode): ILambdaExpressionNode; begin Result := TLambdaExpressionNode.Create(AParameters, ABody); end; class function TAst.UnaryExpr(const AOperator: TUnaryOperator; const ARight: IExpressionNode): IUnaryExpressionNode; begin Result := TUnaryExpressionNode.Create(AOperator, ARight); end; class function TAst.VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode): IVariableDeclarationNode; begin Result := TVariableDeclarationNode.Create(AIdentifier, AInitializer); end; end.