906 lines
30 KiB
ObjectPascal
906 lines
30 KiB
ObjectPascal
unit Myc.Ast;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
System.Classes,
|
|
System.Generics.Collections,
|
|
Myc.Data.Scalar,
|
|
Myc.Data.Value,
|
|
Myc.Data.Keyword,
|
|
Myc.Ast.Nodes,
|
|
Myc.Ast.Scope,
|
|
Myc.Ast.Types,
|
|
Myc.Ast.Identities;
|
|
|
|
type
|
|
TAst = record
|
|
public
|
|
type
|
|
TRegisterLibraryProc = reference to procedure(const Scope: IExecutionScope);
|
|
private
|
|
class var
|
|
FLibraries: TList<TRegisterLibraryProc>;
|
|
class constructor Create;
|
|
class destructor Destroy;
|
|
public
|
|
class procedure RegisterLibrary(const AProc: TRegisterLibraryProc); static;
|
|
class function CreateScope(
|
|
Parent: IExecutionScope;
|
|
const Descriptor: IScopeDescriptor = nil;
|
|
ARegisterLibraries: Boolean = False
|
|
): IExecutionScope; static;
|
|
|
|
// =============================================================================
|
|
// 1. NODES WITH DATA IDENTITIES (Identifier, Constant, Keyword, Definition)
|
|
// =============================================================================
|
|
|
|
// --- IDENTIFIERS ---
|
|
|
|
// [Creation] Raw Name -> New INamedIdentity
|
|
class function Identifier(const AName: string; const Loc: ISourceLocation = nil): IIdentifierNode; overload; static;
|
|
|
|
// [Transformation] Reuse INamedIdentity
|
|
class function Identifier(
|
|
const Identity: INamedIdentity;
|
|
const Address: TResolvedAddress;
|
|
const AStaticType: IStaticType = nil
|
|
): IIdentifierNode; overload; static;
|
|
|
|
// --- CONSTANTS ---
|
|
|
|
// [Creation] Raw Value -> New IConstantIdentity
|
|
class function Constant(const AValue: TDataValue; const Loc: ISourceLocation = nil): IConstantNode; overload; static;
|
|
|
|
class function Constant(const AValue: String; const Loc: ISourceLocation = nil): IConstantNode; overload; static;
|
|
|
|
// [Transformation] Reuse IConstantIdentity
|
|
class function Constant(const Identity: IConstantIdentity; const AStaticType: IStaticType = nil): IConstantNode; overload; static;
|
|
|
|
// --- KEYWORDS ---
|
|
|
|
// [Creation] Raw Name -> New IKeywordIdentity
|
|
class function Keyword(const AName: string; const Loc: ISourceLocation = nil): IKeywordNode; overload; static;
|
|
|
|
// [Transformation] Reuse IKeywordIdentity
|
|
class function Keyword(const Identity: IKeywordIdentity): IKeywordNode; overload; static;
|
|
|
|
// --- DEFINITIONS (CreateSeries) ---
|
|
|
|
// [Creation] Raw Definition String -> New IDefinitionIdentity
|
|
class function CreateSeries(const ADefinition: String; const Loc: ISourceLocation = nil): ICreateSeriesNode; overload; static;
|
|
|
|
// [Transformation] Reuse IDefinitionIdentity
|
|
class function CreateSeries(
|
|
const Identity: IDefinitionIdentity;
|
|
const AStaticType: IStaticType = nil
|
|
): ICreateSeriesNode; overload; static;
|
|
|
|
// =============================================================================
|
|
// 2. STRUCTURAL NODES (Identity is just Location / Marker)
|
|
// =============================================================================
|
|
// Creation: Generates new TStructuralIdentity(Loc)
|
|
// Transformation: Reuses IAstIdentity passed as first param
|
|
|
|
// --- NOP ---
|
|
class function Nop(const Loc: ISourceLocation = nil): IAstNode; overload; static;
|
|
class function Nop(const Identity: IAstIdentity; const AStaticType: IStaticType = nil): IAstNode; overload; static;
|
|
|
|
// --- IF ---
|
|
class function IfExpr(
|
|
const ACondition: IAstNode;
|
|
const AThenBranch, AElseBranch: IAstNode;
|
|
const Loc: ISourceLocation = nil
|
|
): IIfExpressionNode; overload; static;
|
|
|
|
class function IfExpr(
|
|
const Identity: IAstIdentity;
|
|
const ACondition: IAstNode;
|
|
const AThenBranch, AElseBranch: IAstNode;
|
|
const AStaticType: IStaticType = nil
|
|
): IIfExpressionNode; overload; static;
|
|
|
|
// --- TERNARY ---
|
|
class function TernaryExpr(
|
|
const ACondition: IAstNode;
|
|
const AThenBranch, AElseBranch: IAstNode;
|
|
const Loc: ISourceLocation = nil
|
|
): ITernaryExpressionNode; overload; static;
|
|
|
|
class function TernaryExpr(
|
|
const Identity: IAstIdentity;
|
|
const ACondition: IAstNode;
|
|
const AThenBranch, AElseBranch: IAstNode;
|
|
const AStaticType: IStaticType = nil
|
|
): ITernaryExpressionNode; overload; static;
|
|
|
|
// --- LAMBDA ---
|
|
class function LambdaExpr(
|
|
const AParameters: TArray<IIdentifierNode>;
|
|
const ABody: IAstNode;
|
|
const Loc: ISourceLocation = nil
|
|
): ILambdaExpressionNode; overload; static;
|
|
|
|
class function LambdaExpr(
|
|
const Identity: IAstIdentity;
|
|
const AParameters: TArray<IIdentifierNode>;
|
|
const ABody: IAstNode;
|
|
const ALayout: IScopeLayout = nil;
|
|
const ADescriptor: IScopeDescriptor = nil;
|
|
const AUpvalues: TArray<TResolvedAddress> = nil;
|
|
const AHasNestedLambdas: Boolean = False;
|
|
const AIsPure: Boolean = False;
|
|
const AStaticType: IStaticType = nil
|
|
): ILambdaExpressionNode; overload; static;
|
|
|
|
// --- MACRO DEF ---
|
|
class function MacroDef(
|
|
const AName: IIdentifierNode;
|
|
const AParameters: TArray<IIdentifierNode>;
|
|
const ABody: IAstNode;
|
|
const Loc: ISourceLocation = nil
|
|
): IMacroDefinitionNode; overload; static;
|
|
|
|
class function MacroDef(
|
|
const Identity: IAstIdentity;
|
|
const AName: IIdentifierNode;
|
|
const AParameters: TArray<IIdentifierNode>;
|
|
const ABody: IAstNode
|
|
): IMacroDefinitionNode; overload; static;
|
|
|
|
// --- QUOTES ---
|
|
class function Quasiquote(const AExpression: IAstNode; const Loc: ISourceLocation = nil): IQuasiquoteNode; overload; static;
|
|
class function Quasiquote(const Identity: IAstIdentity; const AExpression: IAstNode): IQuasiquoteNode; overload; static;
|
|
|
|
class function Unquote(const AExpression: IAstNode; const Loc: ISourceLocation = nil): IUnquoteNode; overload; static;
|
|
class function Unquote(const Identity: IAstIdentity; const AExpression: IAstNode): IUnquoteNode; overload; static;
|
|
|
|
class function UnquoteSplicing(
|
|
const AExpression: IQuasiquoteNode;
|
|
const Loc: ISourceLocation = nil
|
|
): IUnquoteSplicingNode; overload; static;
|
|
class function UnquoteSplicing(
|
|
const Identity: IAstIdentity;
|
|
const AExpression: IQuasiquoteNode
|
|
): IUnquoteSplicingNode; overload; static;
|
|
|
|
// --- CALL ---
|
|
class function FunctionCall(
|
|
const ACallee: IAstNode;
|
|
const AArguments: TArray<IAstNode>;
|
|
const Loc: ISourceLocation = nil
|
|
): IFunctionCallNode; overload; static;
|
|
|
|
class function FunctionCall(
|
|
const Identity: IAstIdentity;
|
|
const ACallee: IAstNode;
|
|
const AArguments: TArray<IAstNode>;
|
|
const AStaticType: IStaticType = nil;
|
|
const AIsTailCall: Boolean = False;
|
|
const AStaticTarget: TDataValue.TFunc = nil;
|
|
const AIsTargetPure: Boolean = False
|
|
): IFunctionCallNode; overload; static;
|
|
|
|
// --- MACRO EXPANSION ---
|
|
// Note: MacroExpansion is usually created during transformation, but conceptually it's a new node wrapping the original call.
|
|
class function MacroExpansionNode(
|
|
const AOriginalCallNode: IFunctionCallNode;
|
|
const AExpandedBody: IAstNode;
|
|
const Loc: ISourceLocation = nil
|
|
): IMacroExpansionNode; overload; static;
|
|
|
|
class function MacroExpansionNode(
|
|
const Identity: IAstIdentity;
|
|
const AOriginalCallNode: IFunctionCallNode;
|
|
const AExpandedBody: IAstNode
|
|
): IMacroExpansionNode; overload; static;
|
|
|
|
// --- RECUR ---
|
|
class function Recur(const AArguments: array of IAstNode; const Loc: ISourceLocation = nil): IRecurNode; overload; static;
|
|
|
|
class function Recur(
|
|
const Identity: IAstIdentity;
|
|
const AArguments: TArray<IAstNode>;
|
|
const AStaticType: IStaticType = nil
|
|
): IRecurNode; overload; static;
|
|
|
|
// --- BLOCK ---
|
|
class function Block(
|
|
const AExpressions: array of IAstNode;
|
|
const Loc: ISourceLocation = nil
|
|
): IBlockExpressionNode; overload; static;
|
|
|
|
class function Block(
|
|
const Identity: IAstIdentity;
|
|
const AExpressions: TArray<IAstNode>;
|
|
const AStaticType: IStaticType = nil
|
|
): IBlockExpressionNode; overload; static;
|
|
|
|
// --- VAR DECL ---
|
|
class function VarDecl(
|
|
const AIdentifier: IAstNode;
|
|
AInitializer: IAstNode = nil;
|
|
const Loc: ISourceLocation = nil
|
|
): IVariableDeclarationNode; overload; static;
|
|
|
|
class function VarDecl(
|
|
const Identity: IAstIdentity;
|
|
const AIdentifier: IAstNode;
|
|
AInitializer: IAstNode;
|
|
const AStaticType: IStaticType = nil;
|
|
const AIsBoxed: Boolean = False
|
|
): IVariableDeclarationNode; overload; static;
|
|
|
|
// --- ASSIGN ---
|
|
class function Assign(const ATarget, AValue: IAstNode; const Loc: ISourceLocation = nil): IAssignmentNode; overload; static;
|
|
|
|
class function Assign(
|
|
const Identity: IAstIdentity;
|
|
const ATarget, AValue: IAstNode;
|
|
const AStaticType: IStaticType = nil
|
|
): IAssignmentNode; overload; static;
|
|
|
|
// --- ASSIGN RESULT (Helper) ---
|
|
// Special case: Creates implicit nodes. No explicit "Transformation" overload needed as it maps to Assign.
|
|
class function AssignResult(const AValue: IAstNode; const Loc: ISourceLocation = nil): IAssignmentNode; static; deprecated;
|
|
|
|
// --- INDEXER ---
|
|
class function Indexer(
|
|
const ABase: IAstNode;
|
|
const AIndex: IAstNode;
|
|
const Loc: ISourceLocation = nil
|
|
): IIndexerNode; overload; static;
|
|
|
|
class function Indexer(
|
|
const Identity: IAstIdentity;
|
|
const ABase: IAstNode;
|
|
const AIndex: IAstNode;
|
|
const AStaticType: IStaticType = nil
|
|
): IIndexerNode; overload; static;
|
|
|
|
// --- MEMBER ACCESS ---
|
|
class function MemberAccess(
|
|
const ABase: IAstNode;
|
|
const AMember: IKeywordNode;
|
|
const Loc: ISourceLocation = nil
|
|
): IMemberAccessNode; overload; static;
|
|
|
|
class function MemberAccess(
|
|
const Identity: IAstIdentity;
|
|
const ABase: IAstNode;
|
|
const AMember: IKeywordNode;
|
|
const AStaticType: IStaticType = nil
|
|
): IMemberAccessNode; overload; static;
|
|
|
|
// --- RECORD LITERAL ---
|
|
class function RecordLiteral(
|
|
const AFields: TArray<TRecordFieldLiteral>;
|
|
const Loc: ISourceLocation = nil
|
|
): IRecordLiteralNode; overload; static;
|
|
|
|
class function RecordLiteral(
|
|
const Identity: IAstIdentity;
|
|
const AFields: TArray<TRecordFieldLiteral>;
|
|
const AScalarDefinition: IScalarRecordDefinition = nil;
|
|
const AGenericDefinition: IGenericRecordDefinition = nil;
|
|
const AStaticType: IStaticType = nil
|
|
): IRecordLiteralNode; overload; static;
|
|
|
|
// --- SERIES OPS ---
|
|
|
|
class function AddSeriesItem(
|
|
const ASeries: IIdentifierNode;
|
|
const AValue: IAstNode;
|
|
const ALookback: IAstNode = nil;
|
|
const Loc: ISourceLocation = nil
|
|
): IAddSeriesItemNode; overload; static;
|
|
|
|
class function AddSeriesItem(
|
|
const Identity: IAstIdentity;
|
|
const ASeries: IIdentifierNode;
|
|
const AValue: IAstNode;
|
|
const ALookback: IAstNode;
|
|
const AStaticType: IStaticType = nil
|
|
): IAddSeriesItemNode; overload; static;
|
|
|
|
class function SeriesLength(const ASeries: IIdentifierNode; const Loc: ISourceLocation = nil): ISeriesLengthNode; overload; static;
|
|
|
|
class function SeriesLength(
|
|
const Identity: IAstIdentity;
|
|
const ASeries: IIdentifierNode;
|
|
const AStaticType: IStaticType = nil
|
|
): ISeriesLengthNode; overload; static;
|
|
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
System.Generics.Defaults;
|
|
|
|
{ TAst }
|
|
|
|
class constructor TAst.Create;
|
|
begin
|
|
FLibraries := TList<TRegisterLibraryProc>.Create;
|
|
end;
|
|
|
|
class destructor TAst.Destroy;
|
|
begin
|
|
FLibraries.Free;
|
|
end;
|
|
|
|
class procedure TAst.RegisterLibrary(const AProc: TRegisterLibraryProc);
|
|
begin
|
|
FLibraries.Add(AProc);
|
|
end;
|
|
|
|
class function TAst.CreateScope(
|
|
Parent: IExecutionScope;
|
|
const Descriptor: IScopeDescriptor = nil;
|
|
ARegisterLibraries: Boolean = False
|
|
): IExecutionScope;
|
|
begin
|
|
if Assigned(Descriptor) then
|
|
Result := Descriptor.CreateScope(Parent)
|
|
else
|
|
Result := TScope.CreateScope(Parent, nil, nil);
|
|
|
|
if ARegisterLibraries then
|
|
begin
|
|
for var libProc in FLibraries do
|
|
libProc(Result);
|
|
end;
|
|
end;
|
|
|
|
// =============================================================================
|
|
// IMPLEMENTATION: DATA NODES
|
|
// =============================================================================
|
|
|
|
// --- Identifier ---
|
|
|
|
class function TAst.Identifier(const AName: string; const Loc: ISourceLocation): IIdentifierNode;
|
|
begin
|
|
var id := TIdentities.Identifier(AName, Loc);
|
|
Result := TIdentifierNode.Create(id, Default(TResolvedAddress), TTypes.Unknown);
|
|
end;
|
|
|
|
class function TAst.Identifier(
|
|
const Identity: INamedIdentity;
|
|
const Address: TResolvedAddress;
|
|
const AStaticType: IStaticType
|
|
): IIdentifierNode;
|
|
begin
|
|
Result :=
|
|
TIdentifierNode.Create(
|
|
Identity,
|
|
Address,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown
|
|
);
|
|
end;
|
|
|
|
// --- Constant ---
|
|
|
|
class function TAst.Constant(const AValue: TDataValue; const Loc: ISourceLocation): IConstantNode;
|
|
begin
|
|
var constType: IStaticType;
|
|
case AValue.Kind of
|
|
TDataValueKind.vkScalar: constType := TTypes.FromScalarKind(AValue.AsScalar.Kind);
|
|
TDataValueKind.vkText: constType := TTypes.Text;
|
|
TDataValueKind.vkVoid: constType := TTypes.Void;
|
|
else
|
|
constType := TTypes.Unknown;
|
|
end;
|
|
|
|
var id := TIdentities.Constant(AValue, Loc);
|
|
Result := TConstantNode.Create(id, constType);
|
|
end;
|
|
|
|
class function TAst.Constant(const AValue: String; const Loc: ISourceLocation): IConstantNode;
|
|
begin
|
|
Result := TAst.Constant(TDataValue(AValue), Loc);
|
|
end;
|
|
|
|
class function TAst.Constant(const Identity: IConstantIdentity; const AStaticType: IStaticType): IConstantNode;
|
|
begin
|
|
Result :=
|
|
TConstantNode.Create(
|
|
Identity,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown
|
|
);
|
|
end;
|
|
|
|
// --- Keyword ---
|
|
|
|
class function TAst.Keyword(const AName: string; const Loc: ISourceLocation): IKeywordNode;
|
|
begin
|
|
var val := TKeywordRegistry.Intern(AName);
|
|
var id := TIdentities.Keyword(val, Loc);
|
|
Result := TKeywordNode.Create(id);
|
|
end;
|
|
|
|
class function TAst.Keyword(const Identity: IKeywordIdentity): IKeywordNode;
|
|
begin
|
|
Result := TKeywordNode.Create(Identity);
|
|
end;
|
|
|
|
// --- CreateSeries ---
|
|
|
|
class function TAst.CreateSeries(const ADefinition: String; const Loc: ISourceLocation): ICreateSeriesNode;
|
|
begin
|
|
var id := TIdentities.Definition(ADefinition, Loc);
|
|
Result := TCreateSeriesNode.Create(id, TTypes.Unknown);
|
|
end;
|
|
|
|
class function TAst.CreateSeries(const Identity: IDefinitionIdentity; const AStaticType: IStaticType): ICreateSeriesNode;
|
|
begin
|
|
Result :=
|
|
TCreateSeriesNode.Create(
|
|
Identity,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown
|
|
);
|
|
end;
|
|
|
|
// =============================================================================
|
|
// IMPLEMENTATION: STRUCTURAL NODES
|
|
// =============================================================================
|
|
|
|
// --- NOP ---
|
|
|
|
class function TAst.Nop(const Loc: ISourceLocation): IAstNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TNopNode.Create(TTypes.Unknown, id);
|
|
end;
|
|
|
|
class function TAst.Nop(const Identity: IAstIdentity; const AStaticType: IStaticType): IAstNode;
|
|
begin
|
|
Result :=
|
|
TNopNode.Create(
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- IfExpr ---
|
|
|
|
class function TAst.IfExpr(const ACondition, AThenBranch, AElseBranch: IAstNode; const Loc: ISourceLocation): IIfExpressionNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TIfExpressionNode.Create(ACondition, AThenBranch, AElseBranch, TTypes.Unknown, id);
|
|
end;
|
|
|
|
class function TAst.IfExpr(
|
|
const Identity: IAstIdentity;
|
|
const ACondition, AThenBranch, AElseBranch: IAstNode;
|
|
const AStaticType: IStaticType
|
|
): IIfExpressionNode;
|
|
begin
|
|
Result :=
|
|
TIfExpressionNode.Create(
|
|
ACondition,
|
|
AThenBranch,
|
|
AElseBranch,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- TernaryExpr ---
|
|
|
|
class function TAst.TernaryExpr(const ACondition, AThenBranch, AElseBranch: IAstNode; const Loc: ISourceLocation): ITernaryExpressionNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch, TTypes.Unknown, id);
|
|
end;
|
|
|
|
class function TAst.TernaryExpr(
|
|
const Identity: IAstIdentity;
|
|
const ACondition, AThenBranch, AElseBranch: IAstNode;
|
|
const AStaticType: IStaticType
|
|
): ITernaryExpressionNode;
|
|
begin
|
|
Result :=
|
|
TTernaryExpressionNode.Create(
|
|
ACondition,
|
|
AThenBranch,
|
|
AElseBranch,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- LambdaExpr ---
|
|
|
|
class function TAst.LambdaExpr(
|
|
const AParameters: TArray<IIdentifierNode>;
|
|
const ABody: IAstNode;
|
|
const Loc: ISourceLocation
|
|
): ILambdaExpressionNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TLambdaExpressionNode.Create(AParameters, ABody, TTypes.Unknown, nil, nil, nil, False, False, id);
|
|
end;
|
|
|
|
class function TAst.LambdaExpr(
|
|
const Identity: IAstIdentity;
|
|
const AParameters: TArray<IIdentifierNode>;
|
|
const ABody: IAstNode;
|
|
const ALayout: IScopeLayout;
|
|
const ADescriptor: IScopeDescriptor;
|
|
const AUpvalues: TArray<TResolvedAddress>;
|
|
const AHasNestedLambdas, AIsPure: Boolean;
|
|
const AStaticType: IStaticType
|
|
): ILambdaExpressionNode;
|
|
begin
|
|
Result :=
|
|
TLambdaExpressionNode.Create(
|
|
AParameters,
|
|
ABody,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
ALayout,
|
|
ADescriptor,
|
|
AUpvalues,
|
|
AHasNestedLambdas,
|
|
AIsPure,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- MacroDef ---
|
|
|
|
class function TAst.MacroDef(
|
|
const AName: IIdentifierNode;
|
|
const AParameters: TArray<IIdentifierNode>;
|
|
const ABody: IAstNode;
|
|
const Loc: ISourceLocation
|
|
): IMacroDefinitionNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TMacroDefinitionNode.Create(AName, AParameters, ABody, id);
|
|
end;
|
|
|
|
class function TAst.MacroDef(
|
|
const Identity: IAstIdentity;
|
|
const AName: IIdentifierNode;
|
|
const AParameters: TArray<IIdentifierNode>;
|
|
const ABody: IAstNode
|
|
): IMacroDefinitionNode;
|
|
begin
|
|
Result := TMacroDefinitionNode.Create(AName, AParameters, ABody, Identity);
|
|
end;
|
|
|
|
// --- Quotes ---
|
|
|
|
class function TAst.Quasiquote(const AExpression: IAstNode; const Loc: ISourceLocation): IQuasiquoteNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TQuasiquoteNode.Create(AExpression, id);
|
|
end;
|
|
|
|
class function TAst.Quasiquote(const Identity: IAstIdentity; const AExpression: IAstNode): IQuasiquoteNode;
|
|
begin
|
|
Result := TQuasiquoteNode.Create(AExpression, Identity);
|
|
end;
|
|
|
|
class function TAst.Unquote(const AExpression: IAstNode; const Loc: ISourceLocation): IUnquoteNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TUnquoteNode.Create(AExpression, id);
|
|
end;
|
|
|
|
class function TAst.Unquote(const Identity: IAstIdentity; const AExpression: IAstNode): IUnquoteNode;
|
|
begin
|
|
Result := TUnquoteNode.Create(AExpression, Identity);
|
|
end;
|
|
|
|
class function TAst.UnquoteSplicing(const AExpression: IQuasiquoteNode; const Loc: ISourceLocation): IUnquoteSplicingNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TUnquoteSplicingNode.Create(AExpression, id);
|
|
end;
|
|
|
|
class function TAst.UnquoteSplicing(const Identity: IAstIdentity; const AExpression: IQuasiquoteNode): IUnquoteSplicingNode;
|
|
begin
|
|
Result := TUnquoteSplicingNode.Create(AExpression, Identity);
|
|
end;
|
|
|
|
// --- FunctionCall ---
|
|
|
|
class function TAst.FunctionCall(
|
|
const ACallee: IAstNode;
|
|
const AArguments: TArray<IAstNode>;
|
|
const Loc: ISourceLocation
|
|
): IFunctionCallNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TFunctionCallNode.Create(ACallee, AArguments, TTypes.Unknown, False, nil, False, id);
|
|
end;
|
|
|
|
class function TAst.FunctionCall(
|
|
const Identity: IAstIdentity;
|
|
const ACallee: IAstNode;
|
|
const AArguments: TArray<IAstNode>;
|
|
const AStaticType: IStaticType;
|
|
const AIsTailCall: Boolean;
|
|
const AStaticTarget: TDataValue.TFunc;
|
|
const AIsTargetPure: Boolean
|
|
): IFunctionCallNode;
|
|
begin
|
|
Result :=
|
|
TFunctionCallNode.Create(
|
|
ACallee,
|
|
AArguments,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
AIsTailCall,
|
|
AStaticTarget,
|
|
AIsTargetPure,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- MacroExpansion ---
|
|
|
|
class function TAst.MacroExpansionNode(
|
|
const AOriginalCallNode: IFunctionCallNode;
|
|
const AExpandedBody: IAstNode;
|
|
const Loc: ISourceLocation
|
|
): IMacroExpansionNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TMacroExpansionNode.Create(AOriginalCallNode, AExpandedBody, id);
|
|
end;
|
|
|
|
class function TAst.MacroExpansionNode(
|
|
const Identity: IAstIdentity;
|
|
const AOriginalCallNode: IFunctionCallNode;
|
|
const AExpandedBody: IAstNode
|
|
): IMacroExpansionNode;
|
|
begin
|
|
Result := TMacroExpansionNode.Create(AOriginalCallNode, AExpandedBody, Identity);
|
|
end;
|
|
|
|
// --- Recur ---
|
|
|
|
class function TAst.Recur(const AArguments: array of IAstNode; const Loc: ISourceLocation): IRecurNode;
|
|
var
|
|
args: TArray<IAstNode>;
|
|
i: Integer;
|
|
begin
|
|
SetLength(args, Length(AArguments));
|
|
for i := 0 to High(AArguments) do
|
|
args[i] := AArguments[i];
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TRecurNode.Create(args, TTypes.Void, id);
|
|
end;
|
|
|
|
class function TAst.Recur(const Identity: IAstIdentity; const AArguments: TArray<IAstNode>; const AStaticType: IStaticType): IRecurNode;
|
|
begin
|
|
Result :=
|
|
TRecurNode.Create(
|
|
AArguments,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Void,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- Block ---
|
|
|
|
class function TAst.Block(const AExpressions: array of IAstNode; const Loc: ISourceLocation): IBlockExpressionNode;
|
|
var
|
|
exprs: TArray<IAstNode>;
|
|
i: Integer;
|
|
begin
|
|
SetLength(exprs, Length(AExpressions));
|
|
for i := 0 to High(AExpressions) do
|
|
exprs[i] := AExpressions[i];
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TBlockExpressionNode.Create(exprs, TTypes.Unknown, id);
|
|
end;
|
|
|
|
class function TAst.Block(
|
|
const Identity: IAstIdentity;
|
|
const AExpressions: TArray<IAstNode>;
|
|
const AStaticType: IStaticType
|
|
): IBlockExpressionNode;
|
|
begin
|
|
Result :=
|
|
TBlockExpressionNode.Create(
|
|
AExpressions,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- VarDecl ---
|
|
|
|
class function TAst.VarDecl(const AIdentifier: IAstNode; AInitializer: IAstNode; const Loc: ISourceLocation): IVariableDeclarationNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TVariableDeclarationNode.Create(AIdentifier, AInitializer, TTypes.Unknown, False, id);
|
|
end;
|
|
|
|
class function TAst.VarDecl(
|
|
const Identity: IAstIdentity;
|
|
const AIdentifier: IAstNode;
|
|
AInitializer: IAstNode;
|
|
const AStaticType: IStaticType;
|
|
const AIsBoxed: Boolean
|
|
): IVariableDeclarationNode;
|
|
begin
|
|
Result :=
|
|
TVariableDeclarationNode.Create(
|
|
AIdentifier,
|
|
AInitializer,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
AIsBoxed,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- Assign ---
|
|
|
|
class function TAst.Assign(const ATarget, AValue: IAstNode; const Loc: ISourceLocation): IAssignmentNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TAssignmentNode.Create(ATarget, AValue, TTypes.Unknown, id);
|
|
end;
|
|
|
|
class function TAst.Assign(const Identity: IAstIdentity; const ATarget, AValue: IAstNode; const AStaticType: IStaticType): IAssignmentNode;
|
|
begin
|
|
Result :=
|
|
TAssignmentNode.Create(
|
|
ATarget,
|
|
AValue,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
class function TAst.AssignResult(const AValue: IAstNode; const Loc: ISourceLocation): IAssignmentNode;
|
|
begin
|
|
// Helper: Creates an implicit Identifier "Result" with new Identity
|
|
var resultId := TAst.Identifier('Result', Loc);
|
|
Result := TAst.Assign(resultId, AValue, Loc);
|
|
end;
|
|
|
|
// --- Indexer ---
|
|
|
|
class function TAst.Indexer(const ABase, AIndex: IAstNode; const Loc: ISourceLocation): IIndexerNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TIndexerNode.Create(ABase, AIndex, TTypes.Unknown, id);
|
|
end;
|
|
|
|
class function TAst.Indexer(const Identity: IAstIdentity; const ABase, AIndex: IAstNode; const AStaticType: IStaticType): IIndexerNode;
|
|
begin
|
|
Result :=
|
|
TIndexerNode.Create(
|
|
ABase,
|
|
AIndex,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- MemberAccess ---
|
|
|
|
class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IKeywordNode; const Loc: ISourceLocation): IMemberAccessNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TMemberAccessNode.Create(ABase, AMember, TTypes.Unknown, id);
|
|
end;
|
|
|
|
class function TAst.MemberAccess(
|
|
const Identity: IAstIdentity;
|
|
const ABase: IAstNode;
|
|
const AMember: IKeywordNode;
|
|
const AStaticType: IStaticType
|
|
): IMemberAccessNode;
|
|
begin
|
|
Result :=
|
|
TMemberAccessNode.Create(
|
|
ABase,
|
|
AMember,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- RecordLiteral ---
|
|
|
|
class function TAst.RecordLiteral(const AFields: TArray<TRecordFieldLiteral>; const Loc: ISourceLocation): IRecordLiteralNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TRecordLiteralNode.Create(AFields, nil, nil, TTypes.Unknown, id);
|
|
end;
|
|
|
|
class function TAst.RecordLiteral(
|
|
const Identity: IAstIdentity;
|
|
const AFields: TArray<TRecordFieldLiteral>;
|
|
const AScalarDefinition: IScalarRecordDefinition;
|
|
const AGenericDefinition: IGenericRecordDefinition;
|
|
const AStaticType: IStaticType
|
|
): IRecordLiteralNode;
|
|
begin
|
|
Result :=
|
|
TRecordLiteralNode.Create(
|
|
AFields,
|
|
AScalarDefinition,
|
|
AGenericDefinition,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Unknown,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- AddSeriesItem ---
|
|
|
|
class function TAst.AddSeriesItem(
|
|
const ASeries: IIdentifierNode;
|
|
const AValue, ALookback: IAstNode;
|
|
const Loc: ISourceLocation
|
|
): IAddSeriesItemNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TAddSeriesItemNode.Create(ASeries, AValue, ALookback, TTypes.Void, id);
|
|
end;
|
|
|
|
class function TAst.AddSeriesItem(
|
|
const Identity: IAstIdentity;
|
|
const ASeries: IIdentifierNode;
|
|
const AValue, ALookback: IAstNode;
|
|
const AStaticType: IStaticType
|
|
): IAddSeriesItemNode;
|
|
begin
|
|
Result :=
|
|
TAddSeriesItemNode.Create(
|
|
ASeries,
|
|
AValue,
|
|
ALookback,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Void,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
// --- SeriesLength ---
|
|
|
|
class function TAst.SeriesLength(const ASeries: IIdentifierNode; const Loc: ISourceLocation): ISeriesLengthNode;
|
|
begin
|
|
var id := TIdentities.Structural(Loc);
|
|
Result := TSeriesLengthNode.Create(ASeries, TTypes.Ordinal, id);
|
|
end;
|
|
|
|
class function TAst.SeriesLength(
|
|
const Identity: IAstIdentity;
|
|
const ASeries: IIdentifierNode;
|
|
const AStaticType: IStaticType
|
|
): ISeriesLengthNode;
|
|
begin
|
|
Result :=
|
|
TSeriesLengthNode.Create(
|
|
ASeries,
|
|
if AStaticType <> nil then AStaticType
|
|
else TTypes.Ordinal,
|
|
Identity
|
|
);
|
|
end;
|
|
|
|
end.
|