unit Myc.Ast; interface uses System.Classes, System.SysUtils, System.Generics.Collections, System.Generics.Defaults, Myc.Data.Scalar, Myc.Data.Value, Myc.Data.Keyword, Myc.Ast.Nodes, Myc.Ast.Types, Myc.Ast.Scope; type // Record acting as a namespace for the factory functions. TAst = record public type TRegisterLibraryProc = reference to procedure(const Scope: IExecutionScope); private class var FLibraries: TList; class constructor Create; class destructor Destroy; public class procedure RegisterLibrary(const AProc: TRegisterLibraryProc); static; class function CreateScope(Parent: IExecutionScope; const Descriptor: IScopeDescriptor = nil): IExecutionScope; static; // --- Factory functions --- class function Constant(const AValue: TDataValue): IConstantNode; overload; static; class function Constant(const AValue: String): IConstantNode; overload; static; class function Keyword(const AName: string): IKeywordNode; static; class function Identifier(AName: string): IIdentifierNode; static; class function BinaryExpr(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode): IBinaryExpressionNode; static; class function UnaryExpr(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode): IUnaryExpressionNode; static; class function IfExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): IIfExpressionNode; static; class function TernaryExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): ITernaryExpressionNode; static; class function LambdaExpr(const AParameters: TArray; const ABody: IAstNode): ILambdaExpressionNode; static; class function MacroDef( const AName: IIdentifierNode; const AParameters: TArray; const ABody: IQuasiquoteNode ): IMacroDefinitionNode; static; class function Quasiquote(const AExpression: IAstNode): IQuasiquoteNode; static; class function Unquote(const AExpression: IAstNode): IUnquoteNode; static; class function UnquoteSplicing(const AExpression: IAstNode): IUnquoteSplicingNode; static; class function FunctionCall(const ACallee: IAstNode; const AArguments: TArray): IFunctionCallNode; static; class function MacroExpansionNode( const AOriginalCallNode: IFunctionCallNode; const AExpandedBody: IAstNode ): IMacroExpansionNode; static; class function Recur(const AArguments: array of IAstNode): IRecurNode; static; class function Block(const AExpressions: array of IAstNode): IBlockExpressionNode; static; class function VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IAstNode = nil): IVariableDeclarationNode; static; class function Assign(const AIdentifier: IIdentifierNode; const AValue: IAstNode): IAssignmentNode; static; class function AssignResult(const AValue: IAstNode): IAssignmentNode; static; deprecated; class function Indexer(const ABase: IAstNode; const AIndex: IAstNode): IIndexerNode; static; class function MemberAccess(const ABase: IAstNode; const AMember: IIdentifierNode): IMemberAccessNode; static; class function RecordLiteral(const AFields: TArray): IRecordLiteralNode; static; class function CreateSeries(const ADefinition: String): ICreateSeriesNode; static; class function AddSeriesItem( const ASeries: IIdentifierNode; const AValue: IAstNode; const ALookback: IAstNode = nil ): IAddSeriesItemNode; static; class function SeriesLength(const ASeries: IIdentifierNode): ISeriesLengthNode; static; end; // Common base class for AST nodes to reduce boilerplate. TAstNode = class(TInterfacedObject, IAstNode) private FStaticType: IStaticType; public constructor Create; function Accept(const Visitor: IAstVisitor): TDataValue; virtual; abstract; property StaticType: IStaticType read FStaticType write FStaticType; end; TConstantNode = class(TAstNode, IConstantNode) private FValue: TDataValue; function GetValue: TDataValue; public constructor Create(const AValue: TDataValue); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Value: TDataValue read GetValue; end; TIdentifierNode = class(TAstNode, IIdentifierNode) private FName: string; function GetName: string; public constructor Create(AName: string); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Name: string read FName; end; TKeywordNode = class(TAstNode, IKeywordNode) private FValue: IKeyword; function GetValue: IKeyword; public constructor Create(const AName: string); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Value: IKeyword read FValue; end; TBinaryExpressionNode = class(TAstNode, IBinaryExpressionNode) private FLeft: IAstNode; FOperator: TScalar.TBinaryOp; FRight: IAstNode; function GetLeft: IAstNode; function GetOperator: TScalar.TBinaryOp; function GetRight: IAstNode; public constructor Create(const ALeft: IAstNode; AOperator: TScalar.TBinaryOp; const ARight: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TUnaryExpressionNode = class(TAstNode, IUnaryExpressionNode) private FOperator: TScalar.TUnaryOp; FRight: IAstNode; function GetOperator: TScalar.TUnaryOp; function GetRight: IAstNode; public constructor Create(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TIfExpressionNode = class(TAstNode, IIfExpressionNode) private FCondition: IAstNode; FThenBranch: IAstNode; FElseBranch: IAstNode; function GetCondition: IAstNode; function GetThenBranch: IAstNode; function GetElseBranch: IAstNode; public constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TTernaryExpressionNode = class(TAstNode, ITernaryExpressionNode) private FCondition: IAstNode; FThenBranch: IAstNode; FElseBranch: IAstNode; function GetCondition: IAstNode; function GetThenBranch: IAstNode; function GetElseBranch: IAstNode; public constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TLambdaExpressionNode = class(TAstNode, ILambdaExpressionNode) private FParameters: TArray; FBody: IAstNode; function GetParameters: TArray; function GetBody: IAstNode; public constructor Create(const AParameters: TArray; const ABody: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Body: IAstNode read FBody; property Parameters: TArray read FParameters; end; TMacroDefinitionNode = class(TAstNode, IMacroDefinitionNode) private FName: IIdentifierNode; FParameters: TArray; FBody: IQuasiquoteNode; function GetName: IIdentifierNode; function GetParameters: TArray; function GetBody: IQuasiquoteNode; public constructor Create(const AName: IIdentifierNode; const AParameters: TArray; const ABody: IQuasiquoteNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Name: IIdentifierNode read GetName; end; TQuasiquoteNode = class(TAstNode, IQuasiquoteNode) private FExpression: IAstNode; function GetExpression: IAstNode; public constructor Create(const AExpression: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Expression: IAstNode read GetExpression; end; TUnquoteNode = class(TAstNode, IUnquoteNode) private FExpression: IAstNode; function GetExpression: IAstNode; public constructor Create(const AExpression: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TUnquoteSplicingNode = class(TAstNode, IUnquoteSplicingNode) private FExpression: IAstNode; function GetExpression: IAstNode; public constructor Create(const AExpression: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Expression: IAstNode read GetExpression; end; TFunctionCallNode = class(TAstNode, IFunctionCallNode) private FCallee: IAstNode; FArguments: TArray; function GetCallee: IAstNode; function GetArguments: TArray; public constructor Create(const ACallee: IAstNode; const AArguments: TArray); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TMacroExpansionNode = class(TFunctionCallNode, IMacroExpansionNode) private FExpandedBody: IAstNode; function GetExpandedBody: IAstNode; public constructor Create(const AOriginalCallNode: IFunctionCallNode; const AExpandedBody: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TRecurNode = class(TAstNode, IRecurNode) private FArguments: TArray; function GetArguments: TArray; public constructor Create(const AArguments: TArray); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TBlockExpressionNode = class(TAstNode, IBlockExpressionNode) private FExpressions: TArray; function GetExpressions: TArray; public constructor Create(const AExpressions: array of IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Expressions: TArray read FExpressions; end; TVariableDeclarationNode = class(TAstNode, IVariableDeclarationNode) private FIdentifier: IIdentifierNode; FInitializer: IAstNode; function GetIdentifier: IIdentifierNode; function GetInitializer: IAstNode; public constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Identifier: IIdentifierNode read FIdentifier; property Initializer: IAstNode read FInitializer; end; TAssignmentNode = class(TAstNode, IAssignmentNode) private FIdentifier: IIdentifierNode; FValue: IAstNode; function GetIdentifier: IIdentifierNode; function GetValue: IAstNode; public constructor Create(const AIdentifier: IIdentifierNode; const AValue: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TIndexerNode = class(TAstNode, IIndexerNode) private FBase: IAstNode; FIndex: IAstNode; function GetBase: IAstNode; function GetIndex: IAstNode; public constructor Create(const ABase: IAstNode; const AIndex: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TMemberAccessNode = class(TAstNode, IMemberAccessNode) private FBase: IAstNode; FMember: IIdentifierNode; function GetBase: IAstNode; function GetMember: IIdentifierNode; public constructor Create(const ABase: IAstNode; const AMember: IIdentifierNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TRecordLiteralNode = class(TAstNode, IRecordLiteralNode) private FFields: TArray; function GetFields: TArray; public constructor Create(const AFields: TArray); function Accept(const Visitor: IAstVisitor): TDataValue; override; property Fields: TArray read FFields; end; TCreateSeriesNode = class(TAstNode, ICreateSeriesNode) private FDefinition: String; function GetDefinition: String; public constructor Create(const ADefinition: String); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TAddSeriesItemNode = class(TAstNode, IAddSeriesItemNode) private FSeries: IIdentifierNode; FValue: IAstNode; FLookback: IAstNode; function GetSeries: IIdentifierNode; function GetValue: IAstNode; function GetLookback: IAstNode; public constructor Create(const ASeries: IIdentifierNode; const AValue: IAstNode; const ALookback: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TSeriesLengthNode = class(TAstNode, ISeriesLengthNode) private FSeries: IIdentifierNode; function GetSeries: IIdentifierNode; public constructor Create(const ASeries: IIdentifierNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; implementation { TConstantNode } constructor TConstantNode.Create(const AValue: TDataValue); begin inherited Create; // Validate that only allowed constant kinds are used. if not (AValue.Kind in [vkScalar, vkText, vkVoid]) then raise EArgumentException.Create('IConstantNode only supports Scalar, Text, and Void values.'); FValue := AValue; case AValue.Kind of vkScalar: StaticType := TTypes.FromScalarKind(AValue.AsScalar.Kind); vkText: StaticType := TTypes.Text; vkVoid: StaticType := TTypes.Void; else StaticType := TTypes.Unknown; // Should not happen due to validation above end; end; function TConstantNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitConstant(Self); end; function TConstantNode.GetValue: TDataValue; begin Result := FValue; end; { TIdentifierNode } constructor TIdentifierNode.Create(AName: string); begin inherited Create; FName := AName; end; function TIdentifierNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitIdentifier(Self); end; function TIdentifierNode.GetName: string; begin Result := FName; end; { TKeywordNode } constructor TKeywordNode.Create(const AName: string); begin inherited Create; FValue := TKeywordRegistry.Intern(AName); StaticType := TTypes.Keyword; end; function TKeywordNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitKeyword(Self); end; function TKeywordNode.GetValue: IKeyword; begin Result := FValue; end; { TBinaryExpressionNode } constructor TBinaryExpressionNode.Create(const ALeft: IAstNode; AOperator: TScalar.TBinaryOp; const ARight: IAstNode); begin inherited Create; FLeft := ALeft; FOperator := AOperator; FRight := ARight; end; function TBinaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitBinaryExpression(Self); end; function TBinaryExpressionNode.GetLeft: IAstNode; begin Result := FLeft; end; function TBinaryExpressionNode.GetOperator: TScalar.TBinaryOp; begin Result := FOperator; end; function TBinaryExpressionNode.GetRight: IAstNode; begin Result := FRight; end; { TUnaryExpressionNode } constructor TUnaryExpressionNode.Create(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode); begin inherited Create; FOperator := AOperator; FRight := ARight; end; function TUnaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitUnaryExpression(Self); end; function TUnaryExpressionNode.GetOperator: TScalar.TUnaryOp; begin Result := FOperator; end; function TUnaryExpressionNode.GetRight: IAstNode; begin Result := FRight; end; { TIfExpressionNode } constructor TIfExpressionNode.Create(const ACondition, AThenBranch, AElseBranch: IAstNode); begin inherited Create; FCondition := ACondition; FThenBranch := AThenBranch; FElseBranch := AElseBranch; end; function TIfExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitIfExpression(Self); end; function TIfExpressionNode.GetCondition: IAstNode; begin Result := FCondition; end; function TIfExpressionNode.GetElseBranch: IAstNode; begin Result := FElseBranch; end; function TIfExpressionNode.GetThenBranch: IAstNode; begin Result := FThenBranch; end; { TTernaryExpressionNode } constructor TTernaryExpressionNode.Create(const ACondition, AThenBranch, AElseBranch: IAstNode); begin inherited Create; FCondition := ACondition; FThenBranch := AThenBranch; FElseBranch := AElseBranch; end; function TTernaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitTernaryExpression(Self); end; function TTernaryExpressionNode.GetCondition: IAstNode; begin Result := FCondition; end; function TTernaryExpressionNode.GetElseBranch: IAstNode; begin Result := FElseBranch; end; function TTernaryExpressionNode.GetThenBranch: IAstNode; begin Result := FThenBranch; end; { TLambdaExpressionNode } constructor TLambdaExpressionNode.Create(const AParameters: TArray; const ABody: IAstNode); begin inherited Create; FBody := ABody; FParameters := AParameters; end; function TLambdaExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitLambdaExpression(Self); end; function TLambdaExpressionNode.GetBody: IAstNode; begin Result := FBody; end; function TLambdaExpressionNode.GetParameters: TArray; begin Result := FParameters; end; { TMacroDefinitionNode } constructor TMacroDefinitionNode.Create( const AName: IIdentifierNode; const AParameters: TArray; const ABody: IQuasiquoteNode ); begin inherited Create; FName := AName; FParameters := AParameters; FBody := ABody; end; function TMacroDefinitionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitMacroDefinition(Self); end; function TMacroDefinitionNode.GetBody: IQuasiquoteNode; begin Result := FBody; end; function TMacroDefinitionNode.GetName: IIdentifierNode; begin Result := FName; end; function TMacroDefinitionNode.GetParameters: TArray; begin Result := FParameters; end; { TQuasiquoteNode } constructor TQuasiquoteNode.Create(const AExpression: IAstNode); begin inherited Create; FExpression := AExpression; end; function TQuasiquoteNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitQuasiquote(Self); end; function TQuasiquoteNode.GetExpression: IAstNode; begin Result := FExpression; end; { TUnquoteNode } constructor TUnquoteNode.Create(const AExpression: IAstNode); begin inherited Create; FExpression := AExpression; end; function TUnquoteNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitUnquote(Self); end; function TUnquoteNode.GetExpression: IAstNode; begin Result := FExpression; end; { TUnquoteSplicingNode } constructor TUnquoteSplicingNode.Create(const AExpression: IAstNode); begin inherited Create; FExpression := AExpression; end; function TUnquoteSplicingNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitUnquoteSplicing(Self); end; function TUnquoteSplicingNode.GetExpression: IAstNode; begin Result := FExpression; end; { TFunctionCallNode } constructor TFunctionCallNode.Create(const ACallee: IAstNode; const AArguments: TArray); begin inherited Create; FCallee := ACallee; FArguments := AArguments; end; function TFunctionCallNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitFunctionCall(Self); end; function TFunctionCallNode.GetArguments: TArray; begin Result := FArguments; end; function TFunctionCallNode.GetCallee: IAstNode; begin Result := FCallee; end; { TMacroExpansionNode } constructor TMacroExpansionNode.Create(const AOriginalCallNode: IFunctionCallNode; const AExpandedBody: IAstNode); begin inherited Create(AOriginalCallNode.Callee, AOriginalCallNode.Arguments); FExpandedBody := AExpandedBody; end; function TMacroExpansionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitMacroExpansionNode(Self); end; function TMacroExpansionNode.GetExpandedBody: IAstNode; begin Result := FExpandedBody; end; { TRecurNode } constructor TRecurNode.Create(const AArguments: TArray); begin inherited Create; FArguments := AArguments; end; function TRecurNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitRecurNode(Self); end; function TRecurNode.GetArguments: TArray; begin Result := FArguments; end; { TBlockExpressionNode } constructor TBlockExpressionNode.Create(const AExpressions: array of IAstNode); begin inherited Create; SetLength(FExpressions, Length(AExpressions)); TArray.Copy(AExpressions, FExpressions, 0, 0, Length(AExpressions)); end; function TBlockExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitBlockExpression(Self); end; function TBlockExpressionNode.GetExpressions: TArray; begin Result := FExpressions; end; { TVariableDeclarationNode } constructor TVariableDeclarationNode.Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode); begin inherited Create; FIdentifier := AIdentifier; FInitializer := AInitializer; end; function TVariableDeclarationNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitVariableDeclaration(Self); end; function TVariableDeclarationNode.GetIdentifier: IIdentifierNode; begin Result := FIdentifier; end; function TVariableDeclarationNode.GetInitializer: IAstNode; begin Result := FInitializer; end; { TAssignmentNode } constructor TAssignmentNode.Create(const AIdentifier: IIdentifierNode; const AValue: IAstNode); begin inherited Create; FIdentifier := AIdentifier; FValue := AValue; end; function TAssignmentNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitAssignment(Self); end; function TAssignmentNode.GetIdentifier: IIdentifierNode; begin Result := FIdentifier; end; function TAssignmentNode.GetValue: IAstNode; begin Result := FValue; end; { TIndexerNode } constructor TIndexerNode.Create(const ABase, AIndex: IAstNode); begin inherited Create; FBase := ABase; FIndex := AIndex; end; function TIndexerNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitIndexer(Self); end; function TIndexerNode.GetBase: IAstNode; begin Result := FBase; end; function TIndexerNode.GetIndex: IAstNode; begin Result := FIndex; end; { TMemberAccessNode } constructor TMemberAccessNode.Create(const ABase: IAstNode; const AMember: IIdentifierNode); begin inherited Create; FBase := ABase; FMember := AMember; end; function TMemberAccessNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitMemberAccess(Self); end; function TMemberAccessNode.GetBase: IAstNode; begin Result := FBase; end; function TMemberAccessNode.GetMember: IIdentifierNode; begin Result := FMember; end; { TRecordLiteralNode } constructor TRecordLiteralNode.Create(const AFields: TArray); begin inherited Create; FFields := AFields; end; function TRecordLiteralNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitRecordLiteral(Self); end; function TRecordLiteralNode.GetFields: TArray; begin Result := FFields; end; { TCreateSeriesNode } constructor TCreateSeriesNode.Create(const ADefinition: String); begin inherited Create; FDefinition := ADefinition; end; function TCreateSeriesNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitCreateSeries(Self); end; function TCreateSeriesNode.GetDefinition: String; begin Result := FDefinition; end; { TAddSeriesItemNode } constructor TAddSeriesItemNode.Create(const ASeries: IIdentifierNode; const AValue, ALookback: IAstNode); begin inherited Create; FSeries := ASeries; FValue := AValue; FLookback := ALookback; end; function TAddSeriesItemNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitAddSeriesItem(Self); end; function TAddSeriesItemNode.GetLookback: IAstNode; begin Result := FLookback; end; function TAddSeriesItemNode.GetSeries: IIdentifierNode; begin Result := FSeries; end; function TAddSeriesItemNode.GetValue: IAstNode; begin Result := FValue; end; { TSeriesLengthNode } constructor TSeriesLengthNode.Create(const ASeries: IIdentifierNode); begin inherited Create; FSeries := ASeries; end; function TSeriesLengthNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitSeriesLength(Self); end; function TSeriesLengthNode.GetSeries: IIdentifierNode; begin Result := FSeries; end; { TAst } class constructor TAst.Create; begin FLibraries := TList.Create; end; class destructor TAst.Destroy; begin FLibraries.Free; end; class procedure TAst.RegisterLibrary(const AProc: TRegisterLibraryProc); begin FLibraries.Add(AProc); end; class function TAst.AddSeriesItem(const ASeries: IIdentifierNode; const AValue: IAstNode; const ALookback: IAstNode): IAddSeriesItemNode; begin Result := TAddSeriesItemNode.Create(ASeries, AValue, ALookback); end; class function TAst.Assign(const AIdentifier: IIdentifierNode; const AValue: IAstNode): IAssignmentNode; begin Result := TAssignmentNode.Create(AIdentifier, AValue); end; class function TAst.AssignResult(const AValue: IAstNode): IAssignmentNode; begin Result := Assign(TAst.Identifier('Result'), AValue); end; class function TAst.Block(const AExpressions: array of IAstNode): IBlockExpressionNode; begin Result := TBlockExpressionNode.Create(AExpressions); end; class function TAst.Constant(const AValue: TDataValue): IConstantNode; begin Result := TConstantNode.Create(AValue); end; class function TAst.Constant(const AValue: String): IConstantNode; begin Result := TConstantNode.Create(TDataValue(AValue)); end; class function TAst.CreateSeries(const ADefinition: String): ICreateSeriesNode; begin Result := TCreateSeriesNode.Create(ADefinition); end; class function TAst.BinaryExpr(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode): IBinaryExpressionNode; begin Result := TBinaryExpressionNode.Create(ALeft, AOperator, ARight); end; class function TAst.CreateScope(Parent: IExecutionScope; const Descriptor: IScopeDescriptor = nil): IExecutionScope; var proc: TRegisterLibraryProc; begin Result := TScope.CreateScope(Parent, Descriptor, nil); if Parent = nil then begin // When creating a root scope, automatically register all standard libraries. for proc in FLibraries do proc(Result); end; end; class function TAst.FunctionCall(const ACallee: IAstNode; const AArguments: TArray): IFunctionCallNode; begin Result := TFunctionCallNode.Create(ACallee, AArguments); end; class function TAst.MacroExpansionNode(const AOriginalCallNode: IFunctionCallNode; const AExpandedBody: IAstNode): IMacroExpansionNode; begin Result := TMacroExpansionNode.Create(AOriginalCallNode, AExpandedBody); end; class function TAst.Identifier(AName: string): IIdentifierNode; begin Result := TIdentifierNode.Create(AName); end; class function TAst.IfExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): IIfExpressionNode; begin Result := TIfExpressionNode.Create(ACondition, AThenBranch, AElseBranch); end; class function TAst.Indexer(const ABase: IAstNode; const AIndex: IAstNode): IIndexerNode; begin Result := TIndexerNode.Create(ABase, AIndex); end; class function TAst.Keyword(const AName: string): IKeywordNode; begin Result := TKeywordNode.Create(AName); end; class function TAst.LambdaExpr(const AParameters: TArray; const ABody: IAstNode): ILambdaExpressionNode; begin Result := TLambdaExpressionNode.Create(AParameters, ABody); end; class function TAst.MacroDef( const AName: IIdentifierNode; const AParameters: TArray; const ABody: IQuasiquoteNode ): IMacroDefinitionNode; begin Result := TMacroDefinitionNode.Create(AName, AParameters, ABody); end; class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IIdentifierNode): IMemberAccessNode; begin Result := TMemberAccessNode.Create(ABase, AMember); end; class function TAst.Quasiquote(const AExpression: IAstNode): IQuasiquoteNode; begin Result := TQuasiquoteNode.Create(AExpression); end; class function TAst.Recur(const AArguments: array of IAstNode): IRecurNode; var args: TArray; i: Integer; begin SetLength(args, Length(AArguments)); for i := 0 to High(AArguments) do args[i] := AArguments[i]; Result := TRecurNode.Create(args); end; class function TAst.RecordLiteral(const AFields: TArray): IRecordLiteralNode; begin Result := TRecordLiteralNode.Create(AFields); end; class function TAst.SeriesLength(const ASeries: IIdentifierNode): ISeriesLengthNode; begin Result := TSeriesLengthNode.Create(ASeries); end; class function TAst.TernaryExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): ITernaryExpressionNode; begin Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch); end; class function TAst.Unquote(const AExpression: IAstNode): IUnquoteNode; begin Result := TUnquoteNode.Create(AExpression); end; class function TAst.UnquoteSplicing(const AExpression: IAstNode): IUnquoteSplicingNode; begin Result := TUnquoteSplicingNode.Create(AExpression); end; class function TAst.UnaryExpr(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode): IUnaryExpressionNode; begin Result := TUnaryExpressionNode.Create(AOperator, ARight); end; class function TAst.VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IAstNode = nil): IVariableDeclarationNode; begin Result := TVariableDeclarationNode.Create(AIdentifier, AInitializer); end; constructor TAstNode.Create; begin inherited; FStaticType := TTypes.Unknown; end; end.