263 lines
9.1 KiB
ObjectPascal
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.
|