291 lines
10 KiB
ObjectPascal
291 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 Execute(const RootNode: IAstNode): TDataValue;
|
|
|
|
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.
|