Files
MycLib/Src/AST/Myc.Ast.Nodes.pas
T
Michael Schimmel 0cb6f6e85e Refactoring Binder
2025-09-17 14:25:23 +02:00

289 lines
10 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;
IIndexerNode = interface;
IMemberAccessNode = interface;
ICreateSeriesNode = interface;
IAddSeriesItemNode = interface;
ISeriesLengthNode = interface;
IExecutionScope = interface;
IScopeDescriptor = 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;
IValueCell = interface
{$region 'private'}
function GetValue: TDataValue;
procedure SetValue(const AValue: TDataValue);
{$endregion}
property Value: TDataValue read GetValue write SetValue;
end;
IExecutionScope = interface
{$region 'private'}
function GetParent: IExecutionScope;
function GetValues(const Address: TResolvedAddress): TDataValue;
procedure SetValues(const Address: TResolvedAddress; const Value: TDataValue);
{$endregion}
procedure Define(const Name: string; const Value: TDataValue);
function Dump: string;
procedure Clear;
function Capture(const Address: TResolvedAddress): IValueCell;
property Values[const Address: TResolvedAddress]: TDataValue read GetValues write SetValues; default;
property Parent: IExecutionScope read GetParent;
end;
IScopeDescriptor = interface
{$region 'private'}
function GetParent: IScopeDescriptor;
function GetSlotCount: Integer;
function GetSymbols: TDictionary<string, Integer>;
{$endregion}
function CreateScope(const AParent: IExecutionScope): IExecutionScope;
function Define(const Name: string): Integer;
function FindSymbol(const Name: string; out Depth, Index: Integer): Boolean;
property Parent: IScopeDescriptor read GetParent;
property SlotCount: Integer read GetSlotCount;
property Symbols: TDictionary<string, Integer> read GetSymbols;
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 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;
end;
IAstNode = interface(IInterface)
function Accept(const Visitor: IAstVisitor): TDataValue;
end;
IConstantNode = interface(IAstNode)
{$region 'private'}
function GetValue: TScalar;
{$endregion}
property Value: TScalar read GetValue;
end;
IIdentifierNode = interface(IAstNode)
{$region 'private'}
function GetAddress: TResolvedAddress;
function GetName: string;
{$endregion}
property Name: string read GetName;
property Address: TResolvedAddress read GetAddress;
end;
IBinaryExpressionNode = interface(IAstNode)
{$region 'private'}
function GetLeft: IAstNode;
function GetOperator: TBinaryOperator;
function GetRight: IAstNode;
{$endregion}
property Left: IAstNode read GetLeft;
property Operator: TBinaryOperator read GetOperator;
property Right: IAstNode read GetRight;
end;
IUnaryExpressionNode = interface(IAstNode)
{$region 'private'}
function GetOperator: TUnaryOperator;
function GetRight: IAstNode;
{$endregion}
property Operator: TUnaryOperator 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;
function GetScopeDescriptor: IScopeDescriptor;
function GetUpvalues: TArray<TResolvedAddress>;
function GetHasNestedLambdas: Boolean;
{$endregion}
property Parameters: TArray<IIdentifierNode> read GetParameters;
property Body: IAstNode read GetBody;
property ScopeDescriptor: IScopeDescriptor read GetScopeDescriptor;
property Upvalues: TArray<TResolvedAddress> read GetUpvalues;
property HasNestedLambdas: Boolean read GetHasNestedLambdas;
end;
IFunctionCallNode = interface(IAstNode)
{$region 'private'}
function GetCallee: IAstNode;
function GetArguments: TArray<IAstNode>;
function GetIsTailCall: Boolean;
{$endregion}
property Callee: IAstNode read GetCallee;
property Arguments: TArray<IAstNode> read GetArguments;
property IsTailCall: Boolean read GetIsTailCall;
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;
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.