Files
MycLib/Src/AST/Myc.Ast.Nodes.pas
T
Michael Schimmel fd97799b7b added macrodef
2025-10-03 13:49:12 +02:00

263 lines
9.1 KiB
ObjectPascal

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;
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 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<IIdentifierNode>;
function GetBody: IAstNode;
{$endregion}
property Parameters: TArray<IIdentifierNode> read GetParameters;
property Body: IAstNode read GetBody;
end;
IFunctionCallNode = interface(IAstNode)
{$region 'private'}
function GetCallee: IAstNode;
function GetArguments: TArray<IAstNode>;
{$endregion}
property Callee: IAstNode read GetCallee;
property Arguments: TArray<IAstNode> read GetArguments;
end;
// A node representing a tail-recursive call.
IRecurNode = interface(IAstNode)
{$region 'private'}
function GetArguments: TArray<IAstNode>;
{$endregion}
property Arguments: TArray<IAstNode> read GetArguments;
end;
IBlockExpressionNode = interface(IAstNode)
{$region 'private'}
function GetExpressions: TList<IAstNode>;
{$endregion}
property Expressions: TList<IAstNode> 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<IIdentifierNode>;
function GetBody: IAstNode;
{$endregion}
property Name: IIdentifierNode read GetName;
property Parameters: TArray<IIdentifierNode> read GetParameters;
property Body: IAstNode read GetBody;
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;
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.