unit Myc.Ast.Nodes; interface uses System.SysUtils, System.Generics.Collections, Myc.Data.Scalar, Myc.Data.Value; type // --- Forward Declarations to break cycles --- IAstVisitor = interface; IAstNode = interface; IIdentifierNode = interface; IConstantNode = interface; IBinaryExpressionNode = interface; IUnaryExpressionNode = interface; IIfExpressionNode = interface; ITernaryExpressionNode = interface; ILambdaExpressionNode = interface; IFunctionCallNode = interface; IBlockExpressionNode = interface; IVariableDeclarationNode = interface; IAssignmentNode = interface; IMacroDefinitionNode = interface; IQuasiquoteNode = interface; IUnquoteNode = interface; IUnquoteSplicingNode = interface; IIndexerNode = interface; IMemberAccessNode = interface; ICreateSeriesNode = interface; IAddSeriesItemNode = interface; ISeriesLengthNode = interface; IRecurNode = interface; // --- Concrete Type Definitions --- // Defines how an identifier's address was resolved. TAddressKind = (akUnresolved, akLocalOrParent, akUpvalue); TResolvedAddress = record Kind: TAddressKind; ScopeDepth: Integer; SlotIndex: Integer; constructor Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer); class operator Initialize(out Dest: TResolvedAddress); public class operator Equal(const A: TResolvedAddress; B: TResolvedAddress): Boolean; end; IAstVisitor = interface function VisitConstant(const Node: IConstantNode): TDataValue; function VisitIdentifier(const Node: IIdentifierNode): TDataValue; function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; function VisitAssignment(const Node: IAssignmentNode): TDataValue; function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; function VisitUnquote(const Node: IUnquoteNode): TDataValue; function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; function VisitIndexer(const Node: IIndexerNode): TDataValue; function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; function VisitRecurNode(const Node: IRecurNode): TDataValue; end; IAstNode = interface(IInterface) function Accept(const Visitor: IAstVisitor): TDataValue; end; IConstantNode = interface(IAstNode) // Represents a constant value in the AST (Scalar, Text, or Void). {$region 'private'} function GetValue: TDataValue; {$endregion} property Value: TDataValue read GetValue; end; IIdentifierNode = interface(IAstNode) {$region 'private'} function GetName: string; {$endregion} property Name: string read GetName; end; IBinaryExpressionNode = interface(IAstNode) {$region 'private'} function GetLeft: IAstNode; function GetOperator: TScalar.TBinaryOp; function GetRight: IAstNode; {$endregion} property Left: IAstNode read GetLeft; property Operator: TScalar.TBinaryOp read GetOperator; property Right: IAstNode read GetRight; end; IUnaryExpressionNode = interface(IAstNode) {$region 'private'} function GetOperator: TScalar.TUnaryOp; function GetRight: IAstNode; {$endregion} property Operator: TScalar.TUnaryOp read GetOperator; property Right: IAstNode read GetRight; end; IIfExpressionNode = interface(IAstNode) {$region 'private'} function GetCondition: IAstNode; function GetThenBranch: IAstNode; function GetElseBranch: IAstNode; {$endregion} property Condition: IAstNode read GetCondition; property ThenBranch: IAstNode read GetThenBranch; property ElseBranch: IAstNode read GetElseBranch; end; ITernaryExpressionNode = interface(IAstNode) {$region 'private'} function GetCondition: IAstNode; function GetThenBranch: IAstNode; function GetElseBranch: IAstNode; {$endregion} property Condition: IAstNode read GetCondition; property ThenBranch: IAstNode read GetThenBranch; property ElseBranch: IAstNode read GetElseBranch; end; ILambdaExpressionNode = interface(IAstNode) {$region 'private'} function GetParameters: TArray; function GetBody: IAstNode; {$endregion} property Parameters: TArray read GetParameters; property Body: IAstNode read GetBody; end; IFunctionCallNode = interface(IAstNode) {$region 'private'} function GetCallee: IAstNode; function GetArguments: TArray; {$endregion} property Callee: IAstNode read GetCallee; property Arguments: TArray read GetArguments; end; // A node representing a tail-recursive call. IRecurNode = interface(IAstNode) {$region 'private'} function GetArguments: TArray; {$endregion} property Arguments: TArray read GetArguments; end; IBlockExpressionNode = interface(IAstNode) {$region 'private'} function GetExpressions: TArray; {$endregion} property Expressions: TArray read GetExpressions; end; IVariableDeclarationNode = interface(IAstNode) {$region 'private'} function GetIdentifier: IIdentifierNode; function GetInitializer: IAstNode; {$endregion} property Identifier: IIdentifierNode read GetIdentifier; property Initializer: IAstNode read GetInitializer; end; IAssignmentNode = interface(IAstNode) {$region 'private'} function GetIdentifier: IIdentifierNode; function GetValue: IAstNode; {$endregion} property Identifier: IIdentifierNode read GetIdentifier; property Value: IAstNode read GetValue; end; IMacroDefinitionNode = interface(IAstNode) {$region 'private'} function GetName: IIdentifierNode; function GetParameters: TArray; function GetBody: IAstNode; {$endregion} property Name: IIdentifierNode read GetName; property Parameters: TArray read GetParameters; property Body: IAstNode read GetBody; end; // Represents a quasiquoted expression, e.g., `(a b) IQuasiquoteNode = interface(IAstNode) {$region 'private'} function GetExpression: IAstNode; {$endregion} property Expression: IAstNode read GetExpression; end; // Represents an unquoted expression, e.g., ~x IUnquoteNode = interface(IAstNode) {$region 'private'} function GetExpression: IAstNode; {$endregion} property Expression: IAstNode read GetExpression; end; // Represents an unquote-splicing expression, e.g., ~@y IUnquoteSplicingNode = interface(IAstNode) {$region 'private'} function GetExpression: IAstNode; {$endregion} property Expression: IAstNode read GetExpression; end; IIndexerNode = interface(IAstNode) {$region 'private'} function GetBase: IAstNode; function GetIndex: IAstNode; {$endregion} property Base: IAstNode read GetBase; property Index: IAstNode read GetIndex; end; IMemberAccessNode = interface(IAstNode) {$region 'private'} function GetBase: IAstNode; function GetMember: IIdentifierNode; {$endregion} property Base: IAstNode read GetBase; property Member: IIdentifierNode read GetMember; end; ICreateSeriesNode = interface(IAstNode) {$region 'private'} function GetDefinition: String; {$endregion} property Definition: String read GetDefinition; end; IAddSeriesItemNode = interface(IAstNode) {$region 'private'} function GetSeries: IIdentifierNode; function GetValue: IAstNode; function GetLookback: IAstNode; {$endregion} property Series: IIdentifierNode read GetSeries; property Value: IAstNode read GetValue; property Lookback: IAstNode read GetLookback; end; ISeriesLengthNode = interface(IAstNode) {$region 'private'} function GetSeries: IIdentifierNode; {$endregion} property Series: IIdentifierNode read GetSeries; end; IEvaluatorVisitor = interface(IAstVisitor) function Execute(const RootNode: IAstNode): TDataValue; end; implementation uses System.Classes; { TResolvedAddress } constructor TResolvedAddress.Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer); begin Kind := AKind; ScopeDepth := AScopeDepth; SlotIndex := ASlotIndex; end; class operator TResolvedAddress.Equal(const A: TResolvedAddress; B: TResolvedAddress): Boolean; begin Result := (A.Kind = B.Kind) and (A.ScopeDepth = B.ScopeDepth) and (A.SlotIndex = B.SlotIndex); end; class operator TResolvedAddress.Initialize(out Dest: TResolvedAddress); begin Dest.Kind := akUnresolved; Dest.ScopeDepth := -1; Dest.SlotIndex := -1; end; end.