Files
MycLib/Src/AST/Myc.Ast.pas
T
2025-10-03 14:17:34 +02:00

952 lines
28 KiB
ObjectPascal

unit Myc.Ast;
interface
uses
System.Classes,
System.SysUtils,
System.Generics.Collections,
System.Generics.Defaults,
Myc.Data.Scalar,
Myc.Data.Value,
Myc.Ast.Nodes,
Myc.Ast.Scope;
type
// Record acting as a namespace for the factory functions.
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): IExecutionScope; static;
// --- Factory functions ---
class function Constant(const AValue: TDataValue): IConstantNode; overload; static;
class function Constant(const AValue: String): IConstantNode; overload; static;
class function Identifier(AName: string): IIdentifierNode; static;
class function BinaryExpr(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode): IBinaryExpressionNode; static;
class function UnaryExpr(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode): IUnaryExpressionNode; static;
class function IfExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): IIfExpressionNode; static;
class function TernaryExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): ITernaryExpressionNode; static;
class function LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode; static;
class function MacroDef(
const AName: IIdentifierNode;
const AParameters: TArray<IIdentifierNode>;
const ABody: IAstNode
): IMacroDefinitionNode; static;
class function Quasiquote(const AExpression: IAstNode): IQuasiquoteNode; static;
class function Unquote(const AExpression: IAstNode): IUnquoteNode; static;
class function UnquoteSplicing(const AExpression: IAstNode): IUnquoteSplicingNode; static;
class function FunctionCall(const ACallee: IAstNode; const AArguments: TArray<IAstNode>): IFunctionCallNode; static;
class function Recur(const AArguments: array of IAstNode): IRecurNode; static;
class function Block(const AExpressions: array of IAstNode): IBlockExpressionNode; static;
class function VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IAstNode = nil): IVariableDeclarationNode; static;
class function Assign(const AIdentifier: IIdentifierNode; const AValue: IAstNode): IAssignmentNode; static;
class function AssignResult(const AValue: IAstNode): IAssignmentNode; static; deprecated;
class function Indexer(const ABase: IAstNode; const AIndex: IAstNode): IIndexerNode; static;
class function MemberAccess(const ABase: IAstNode; const AMember: IIdentifierNode): IMemberAccessNode; static;
class function CreateSeries(const ADefinition: String): ICreateSeriesNode; static;
class function AddSeriesItem(
const ASeries: IIdentifierNode;
const AValue: IAstNode;
const ALookback: IAstNode = nil
): IAddSeriesItemNode; static;
class function SeriesLength(const ASeries: IIdentifierNode): ISeriesLengthNode; static;
end;
// Common base class for AST nodes to reduce boilerplate.
TAstNode = class(TInterfacedObject, IAstNode)
public
function Accept(const Visitor: IAstVisitor): TDataValue; virtual; abstract;
end;
TConstantNode = class(TAstNode, IConstantNode)
private
FValue: TDataValue;
function GetValue: TDataValue;
public
constructor Create(const AValue: TDataValue);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TIdentifierNode = class(TAstNode, IIdentifierNode)
private
FName: string;
function GetName: string;
public
constructor Create(AName: string);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
property Name: string read FName;
end;
TBinaryExpressionNode = class(TAstNode, IBinaryExpressionNode)
private
FLeft: IAstNode;
FOperator: TScalar.TBinaryOp;
FRight: IAstNode;
function GetLeft: IAstNode;
function GetOperator: TScalar.TBinaryOp;
function GetRight: IAstNode;
public
constructor Create(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TUnaryExpressionNode = class(TAstNode, IUnaryExpressionNode)
private
FOperator: TScalar.TUnaryOp;
FRight: IAstNode;
function GetOperator: TScalar.TUnaryOp;
function GetRight: IAstNode;
public
constructor Create(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TIfExpressionNode = class(TAstNode, IIfExpressionNode)
private
FCondition: IAstNode;
FThenBranch: IAstNode;
FElseBranch: IAstNode;
function GetCondition: IAstNode;
function GetThenBranch: IAstNode;
function GetElseBranch: IAstNode;
public
constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TTernaryExpressionNode = class(TAstNode, ITernaryExpressionNode)
private
FCondition: IAstNode;
FThenBranch: IAstNode;
FElseBranch: IAstNode;
function GetCondition: IAstNode;
function GetThenBranch: IAstNode;
function GetElseBranch: IAstNode;
public
constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TLambdaExpressionNode = class(TAstNode, ILambdaExpressionNode)
private
FParameters: TArray<IIdentifierNode>;
FBody: IAstNode;
function GetParameters: TArray<IIdentifierNode>;
function GetBody: IAstNode;
public
constructor Create(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
property Body: IAstNode read FBody;
property Parameters: TArray<IIdentifierNode> read FParameters;
end;
TMacroDefinitionNode = class(TAstNode, IMacroDefinitionNode)
private
FName: IIdentifierNode;
FParameters: TArray<IIdentifierNode>;
FBody: IAstNode;
function GetName: IIdentifierNode;
function GetParameters: TArray<IIdentifierNode>;
function GetBody: IAstNode;
public
constructor Create(const AName: IIdentifierNode; const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TQuasiquoteNode = class(TAstNode, IQuasiquoteNode)
private
FExpression: IAstNode;
function GetExpression: IAstNode;
public
constructor Create(const AExpression: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TUnquoteNode = class(TAstNode, IUnquoteNode)
private
FExpression: IAstNode;
function GetExpression: IAstNode;
public
constructor Create(const AExpression: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TUnquoteSplicingNode = class(TAstNode, IUnquoteSplicingNode)
private
FExpression: IAstNode;
function GetExpression: IAstNode;
public
constructor Create(const AExpression: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TFunctionCallNode = class(TAstNode, IFunctionCallNode)
private
FCallee: IAstNode;
FArguments: TArray<IAstNode>;
function GetCallee: IAstNode;
function GetArguments: TArray<IAstNode>;
public
constructor Create(const ACallee: IAstNode; const AArguments: TArray<IAstNode>);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TRecurNode = class(TAstNode, IRecurNode)
private
FArguments: TArray<IAstNode>;
function GetArguments: TArray<IAstNode>;
public
constructor Create(const AArguments: TArray<IAstNode>);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TBlockExpressionNode = class(TAstNode, IBlockExpressionNode)
private
FExpressions: TList<IAstNode>;
function GetExpressions: TList<IAstNode>;
public
constructor Create(const AExpressions: array of IAstNode);
destructor Destroy; override;
function Accept(const Visitor: IAstVisitor): TDataValue; override;
property Expressions: TList<IAstNode> read FExpressions;
end;
TVariableDeclarationNode = class(TAstNode, IVariableDeclarationNode)
private
FIdentifier: IIdentifierNode;
FInitializer: IAstNode;
function GetIdentifier: IIdentifierNode;
function GetInitializer: IAstNode;
public
constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
property Identifier: IIdentifierNode read FIdentifier;
property Initializer: IAstNode read FInitializer;
end;
TAssignmentNode = class(TAstNode, IAssignmentNode)
private
FIdentifier: IIdentifierNode;
FValue: IAstNode;
function GetIdentifier: IIdentifierNode;
function GetValue: IAstNode;
public
constructor Create(const AIdentifier: IIdentifierNode; const AValue: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TIndexerNode = class(TAstNode, IIndexerNode)
private
FBase: IAstNode;
FIndex: IAstNode;
function GetBase: IAstNode;
function GetIndex: IAstNode;
public
constructor Create(const ABase: IAstNode; const AIndex: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TMemberAccessNode = class(TAstNode, IMemberAccessNode)
private
FBase: IAstNode;
FMember: IIdentifierNode;
function GetBase: IAstNode;
function GetMember: IIdentifierNode;
public
constructor Create(const ABase: IAstNode; const AMember: IIdentifierNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TCreateSeriesNode = class(TAstNode, ICreateSeriesNode)
private
FDefinition: String;
function GetDefinition: String;
public
constructor Create(const ADefinition: String);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TAddSeriesItemNode = class(TAstNode, IAddSeriesItemNode)
private
FSeries: IIdentifierNode;
FValue: IAstNode;
FLookback: IAstNode;
function GetSeries: IIdentifierNode;
function GetValue: IAstNode;
function GetLookback: IAstNode;
public
constructor Create(const ASeries: IIdentifierNode; const AValue: IAstNode; const ALookback: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
TSeriesLengthNode = class(TAstNode, ISeriesLengthNode)
private
FSeries: IIdentifierNode;
function GetSeries: IIdentifierNode;
public
constructor Create(const ASeries: IIdentifierNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
end;
implementation
{ TConstantNode }
constructor TConstantNode.Create(const AValue: TDataValue);
begin
inherited Create;
// Validate that only allowed constant kinds are used.
if not (AValue.Kind in [vkScalar, vkText, vkVoid]) then
raise EArgumentException.Create('IConstantNode only supports Scalar, Text, and Void values.');
FValue := AValue;
end;
function TConstantNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitConstant(Self);
end;
function TConstantNode.GetValue: TDataValue;
begin
Result := FValue;
end;
{ TIdentifierNode }
constructor TIdentifierNode.Create(AName: string);
begin
inherited Create;
FName := AName;
end;
function TIdentifierNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitIdentifier(Self);
end;
function TIdentifierNode.GetName: string;
begin
Result := FName;
end;
{ TBinaryExpressionNode }
constructor TBinaryExpressionNode.Create(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode);
begin
inherited Create;
FLeft := ALeft;
FOperator := AOperator;
FRight := ARight;
end;
function TBinaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitBinaryExpression(Self);
end;
function TBinaryExpressionNode.GetLeft: IAstNode;
begin
Result := FLeft;
end;
function TBinaryExpressionNode.GetOperator: TScalar.TBinaryOp;
begin
Result := FOperator;
end;
function TBinaryExpressionNode.GetRight: IAstNode;
begin
Result := FRight;
end;
{ TUnaryExpressionNode }
constructor TUnaryExpressionNode.Create(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode);
begin
inherited Create;
FOperator := AOperator;
FRight := ARight;
end;
function TUnaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitUnaryExpression(Self);
end;
function TUnaryExpressionNode.GetOperator: TScalar.TUnaryOp;
begin
Result := FOperator;
end;
function TUnaryExpressionNode.GetRight: IAstNode;
begin
Result := FRight;
end;
{ TIfExpressionNode }
constructor TIfExpressionNode.Create(const ACondition, AThenBranch, AElseBranch: IAstNode);
begin
inherited Create;
FCondition := ACondition;
FThenBranch := AThenBranch;
FElseBranch := AElseBranch;
end;
function TIfExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitIfExpression(Self);
end;
function TIfExpressionNode.GetCondition: IAstNode;
begin
Result := FCondition;
end;
function TIfExpressionNode.GetElseBranch: IAstNode;
begin
Result := FElseBranch;
end;
function TIfExpressionNode.GetThenBranch: IAstNode;
begin
Result := FThenBranch;
end;
{ TTernaryExpressionNode }
constructor TTernaryExpressionNode.Create(const ACondition, AThenBranch, AElseBranch: IAstNode);
begin
inherited Create;
FCondition := ACondition;
FThenBranch := AThenBranch;
FElseBranch := AElseBranch;
end;
function TTernaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitTernaryExpression(Self);
end;
function TTernaryExpressionNode.GetCondition: IAstNode;
begin
Result := FCondition;
end;
function TTernaryExpressionNode.GetElseBranch: IAstNode;
begin
Result := FElseBranch;
end;
function TTernaryExpressionNode.GetThenBranch: IAstNode;
begin
Result := FThenBranch;
end;
{ TLambdaExpressionNode }
constructor TLambdaExpressionNode.Create(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
begin
inherited Create;
FBody := ABody;
FParameters := AParameters;
end;
function TLambdaExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitLambdaExpression(Self);
end;
function TLambdaExpressionNode.GetBody: IAstNode;
begin
Result := FBody;
end;
function TLambdaExpressionNode.GetParameters: TArray<IIdentifierNode>;
begin
Result := FParameters;
end;
{ TMacroDefinitionNode }
constructor TMacroDefinitionNode.Create(const AName: IIdentifierNode; const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
begin
inherited Create;
FName := AName;
FParameters := AParameters;
FBody := ABody;
end;
function TMacroDefinitionNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitMacroDefinition(Self);
end;
function TMacroDefinitionNode.GetBody: IAstNode;
begin
Result := FBody;
end;
function TMacroDefinitionNode.GetName: IIdentifierNode;
begin
Result := FName;
end;
function TMacroDefinitionNode.GetParameters: TArray<IIdentifierNode>;
begin
Result := FParameters;
end;
{ TQuasiquoteNode }
constructor TQuasiquoteNode.Create(const AExpression: IAstNode);
begin
inherited Create;
FExpression := AExpression;
end;
function TQuasiquoteNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitQuasiquote(Self);
end;
function TQuasiquoteNode.GetExpression: IAstNode;
begin
Result := FExpression;
end;
{ TUnquoteNode }
constructor TUnquoteNode.Create(const AExpression: IAstNode);
begin
inherited Create;
FExpression := AExpression;
end;
function TUnquoteNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitUnquote(Self);
end;
function TUnquoteNode.GetExpression: IAstNode;
begin
Result := FExpression;
end;
{ TUnquoteSplicingNode }
constructor TUnquoteSplicingNode.Create(const AExpression: IAstNode);
begin
inherited Create;
FExpression := AExpression;
end;
function TUnquoteSplicingNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitUnquoteSplicing(Self);
end;
function TUnquoteSplicingNode.GetExpression: IAstNode;
begin
Result := FExpression;
end;
{ TFunctionCallNode }
constructor TFunctionCallNode.Create(const ACallee: IAstNode; const AArguments: TArray<IAstNode>);
begin
inherited Create;
FCallee := ACallee;
FArguments := AArguments;
end;
function TFunctionCallNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitFunctionCall(Self);
end;
function TFunctionCallNode.GetArguments: TArray<IAstNode>;
begin
Result := FArguments;
end;
function TFunctionCallNode.GetCallee: IAstNode;
begin
Result := FCallee;
end;
{ TRecurNode }
constructor TRecurNode.Create(const AArguments: TArray<IAstNode>);
begin
inherited Create;
FArguments := AArguments;
end;
function TRecurNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitRecurNode(Self);
end;
function TRecurNode.GetArguments: TArray<IAstNode>;
begin
Result := FArguments;
end;
{ TBlockExpressionNode }
constructor TBlockExpressionNode.Create(const AExpressions: array of IAstNode);
var
expr: IAstNode;
begin
inherited Create;
FExpressions := TList<IAstNode>.Create;
for expr in AExpressions do
FExpressions.Add(expr);
end;
destructor TBlockExpressionNode.Destroy;
begin
FExpressions.Free;
inherited;
end;
function TBlockExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitBlockExpression(Self);
end;
function TBlockExpressionNode.GetExpressions: TList<IAstNode>;
begin
Result := FExpressions;
end;
{ TVariableDeclarationNode }
constructor TVariableDeclarationNode.Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode);
begin
inherited Create;
FIdentifier := AIdentifier;
FInitializer := AInitializer;
end;
function TVariableDeclarationNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitVariableDeclaration(Self);
end;
function TVariableDeclarationNode.GetIdentifier: IIdentifierNode;
begin
Result := FIdentifier;
end;
function TVariableDeclarationNode.GetInitializer: IAstNode;
begin
Result := FInitializer;
end;
{ TAssignmentNode }
constructor TAssignmentNode.Create(const AIdentifier: IIdentifierNode; const AValue: IAstNode);
begin
inherited Create;
FIdentifier := AIdentifier;
FValue := AValue;
end;
function TAssignmentNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitAssignment(Self);
end;
function TAssignmentNode.GetIdentifier: IIdentifierNode;
begin
Result := FIdentifier;
end;
function TAssignmentNode.GetValue: IAstNode;
begin
Result := FValue;
end;
{ TIndexerNode }
constructor TIndexerNode.Create(const ABase, AIndex: IAstNode);
begin
inherited Create;
FBase := ABase;
FIndex := AIndex;
end;
function TIndexerNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitIndexer(Self);
end;
function TIndexerNode.GetBase: IAstNode;
begin
Result := FBase;
end;
function TIndexerNode.GetIndex: IAstNode;
begin
Result := FIndex;
end;
{ TMemberAccessNode }
constructor TMemberAccessNode.Create(const ABase: IAstNode; const AMember: IIdentifierNode);
begin
inherited Create;
FBase := ABase;
FMember := AMember;
end;
function TMemberAccessNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitMemberAccess(Self);
end;
function TMemberAccessNode.GetBase: IAstNode;
begin
Result := FBase;
end;
function TMemberAccessNode.GetMember: IIdentifierNode;
begin
Result := FMember;
end;
{ TCreateSeriesNode }
constructor TCreateSeriesNode.Create(const ADefinition: String);
begin
inherited Create;
FDefinition := ADefinition;
end;
function TCreateSeriesNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitCreateSeries(Self);
end;
function TCreateSeriesNode.GetDefinition: String;
begin
Result := FDefinition;
end;
{ TAddSeriesItemNode }
constructor TAddSeriesItemNode.Create(const ASeries: IIdentifierNode; const AValue, ALookback: IAstNode);
begin
inherited Create;
FSeries := ASeries;
FValue := AValue;
FLookback := ALookback;
end;
function TAddSeriesItemNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitAddSeriesItem(Self);
end;
function TAddSeriesItemNode.GetLookback: IAstNode;
begin
Result := FLookback;
end;
function TAddSeriesItemNode.GetSeries: IIdentifierNode;
begin
Result := FSeries;
end;
function TAddSeriesItemNode.GetValue: IAstNode;
begin
Result := FValue;
end;
{ TSeriesLengthNode }
constructor TSeriesLengthNode.Create(const ASeries: IIdentifierNode);
begin
inherited Create;
FSeries := ASeries;
end;
function TSeriesLengthNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitSeriesLength(Self);
end;
function TSeriesLengthNode.GetSeries: IIdentifierNode;
begin
Result := FSeries;
end;
{ 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.AddSeriesItem(const ASeries: IIdentifierNode; const AValue: IAstNode; const ALookback: IAstNode): IAddSeriesItemNode;
begin
Result := TAddSeriesItemNode.Create(ASeries, AValue, ALookback);
end;
class function TAst.Assign(const AIdentifier: IIdentifierNode; const AValue: IAstNode): IAssignmentNode;
begin
Result := TAssignmentNode.Create(AIdentifier, AValue);
end;
class function TAst.AssignResult(const AValue: IAstNode): IAssignmentNode;
begin
Result := Assign(TAst.Identifier('Result'), AValue);
end;
class function TAst.Block(const AExpressions: array of IAstNode): IBlockExpressionNode;
begin
Result := TBlockExpressionNode.Create(AExpressions);
end;
class function TAst.Constant(const AValue: TDataValue): IConstantNode;
begin
Result := TConstantNode.Create(AValue);
end;
class function TAst.Constant(const AValue: String): IConstantNode;
begin
Result := TConstantNode.Create(TDataValue(AValue));
end;
class function TAst.CreateSeries(const ADefinition: String): ICreateSeriesNode;
begin
Result := TCreateSeriesNode.Create(ADefinition);
end;
class function TAst.BinaryExpr(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode): IBinaryExpressionNode;
begin
Result := TBinaryExpressionNode.Create(ALeft, AOperator, ARight);
end;
class function TAst.CreateScope(Parent: IExecutionScope; const Descriptor: IScopeDescriptor = nil): IExecutionScope;
var
proc: TRegisterLibraryProc;
begin
Result := TScope.CreateScope(Parent, Descriptor, nil);
if Parent = nil then
begin
// When creating a root scope, automatically register all standard libraries.
for proc in FLibraries do
proc(Result);
end;
end;
class function TAst.FunctionCall(const ACallee: IAstNode; const AArguments: TArray<IAstNode>): IFunctionCallNode;
begin
Result := TFunctionCallNode.Create(ACallee, AArguments);
end;
class function TAst.Identifier(AName: string): IIdentifierNode;
begin
Result := TIdentifierNode.Create(AName);
end;
class function TAst.IfExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): IIfExpressionNode;
begin
Result := TIfExpressionNode.Create(ACondition, AThenBranch, AElseBranch);
end;
class function TAst.Indexer(const ABase: IAstNode; const AIndex: IAstNode): IIndexerNode;
begin
Result := TIndexerNode.Create(ABase, AIndex);
end;
class function TAst.LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode;
begin
Result := TLambdaExpressionNode.Create(AParameters, ABody);
end;
class function TAst.MacroDef(
const AName: IIdentifierNode;
const AParameters: TArray<IIdentifierNode>;
const ABody: IAstNode
): IMacroDefinitionNode;
begin
Result := TMacroDefinitionNode.Create(AName, AParameters, ABody);
end;
class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IIdentifierNode): IMemberAccessNode;
begin
Result := TMemberAccessNode.Create(ABase, AMember);
end;
class function TAst.Quasiquote(const AExpression: IAstNode): IQuasiquoteNode;
begin
Result := TQuasiquoteNode.Create(AExpression);
end;
class function TAst.Recur(const AArguments: array of IAstNode): IRecurNode;
var
args: TArray<IAstNode>;
i: Integer;
begin
SetLength(args, Length(AArguments));
for i := 0 to High(AArguments) do
args[i] := AArguments[i];
Result := TRecurNode.Create(args);
end;
class function TAst.SeriesLength(const ASeries: IIdentifierNode): ISeriesLengthNode;
begin
Result := TSeriesLengthNode.Create(ASeries);
end;
class function TAst.TernaryExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): ITernaryExpressionNode;
begin
Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch);
end;
class function TAst.Unquote(const AExpression: IAstNode): IUnquoteNode;
begin
Result := TUnquoteNode.Create(AExpression);
end;
class function TAst.UnquoteSplicing(const AExpression: IAstNode): IUnquoteSplicingNode;
begin
Result := TUnquoteSplicingNode.Create(AExpression);
end;
class function TAst.UnaryExpr(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode): IUnaryExpressionNode;
begin
Result := TUnaryExpressionNode.Create(AOperator, ARight);
end;
class function TAst.VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IAstNode = nil): IVariableDeclarationNode;
begin
Result := TVariableDeclarationNode.Create(AIdentifier, AInitializer);
end;
end.