Files
MycLib/Src/AST/Myc.Ast.pas
T
Michael Schimmel fa9328a183 AST refactoring
2025-08-29 09:44:17 +02:00

473 lines
14 KiB
ObjectPascal

unit Myc.Ast;
interface
uses
System.SysUtils,
Myc.Data.POD,
Myc.Ast.Nodes;
type
// Record acting as a namespace for the factory functions.
TAst = record
class function Constant(AValue: TScalar): IConstantNode; static;
class function Identifier(AName: string): IIdentifierNode; static;
class function BinaryExpr(
ALeft: IExpressionNode;
AOperator: TBinaryOperator;
ARight: IExpressionNode
): IBinaryExpressionNode; static;
class function UnaryExpr(const AOperator: TUnaryOperator; const ARight: IExpressionNode): IUnaryExpressionNode; static;
class function IfExpr(
const ACondition: IExpressionNode;
const AThenBranch, AElseBranch: IExpressionNode
): IIfExpressionNode; static;
class function LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode): ILambdaExpressionNode; static;
class function FunctionCall(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode): IFunctionCallNode; static;
class function Block(const AExpressions: array of IExpressionNode): IBlockExpressionNode; static;
class function VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode): IVariableDeclarationNode; static;
class function Assign(const AIdentifier: IIdentifierNode; const AValue: IExpressionNode): IAssignmentNode; static;
end;
implementation
uses
System.Classes,
System.Generics.Collections;
type
{ TAstNode }
// Common base class for AST nodes to reduce boilerplate.
TAstNode = class(TInterfacedObject, IExpressionNode)
public
function Accept(const Visitor: IAstVisitor): TAstValue; virtual; abstract;
end;
{ TConstantNode }
TConstantNode = class(TAstNode, IConstantNode)
private
FValue: TScalar;
function GetValue: TScalar;
public
constructor Create(AValue: TScalar);
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TIdentifierNode }
TIdentifierNode = class(TAstNode, IIdentifierNode)
private
FName: string;
function GetName: string;
public
constructor Create(AName: string);
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TBinaryExpressionNode }
TBinaryExpressionNode = class(TAstNode, IBinaryExpressionNode)
private
FLeft: IExpressionNode;
FOperator: TBinaryOperator;
FRight: IExpressionNode;
function GetLeft: IExpressionNode;
function GetOperator: TBinaryOperator;
function GetRight: IExpressionNode;
public
constructor Create(ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode);
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TUnaryExpressionNode }
TUnaryExpressionNode = class(TAstNode, IUnaryExpressionNode)
private
FOperator: TUnaryOperator;
FRight: IExpressionNode;
function GetOperator: TUnaryOperator;
function GetRight: IExpressionNode;
public
constructor Create(const AOperator: TUnaryOperator; const ARight: IExpressionNode);
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TIfExpressionNode }
TIfExpressionNode = class(TAstNode, IIfExpressionNode)
private
FCondition: IExpressionNode;
FThenBranch: IExpressionNode;
FElseBranch: IExpressionNode;
function GetCondition: IExpressionNode;
function GetThenBranch: IExpressionNode;
function GetElseBranch: IExpressionNode;
public
constructor Create(const ACondition, AThenBranch, AElseBranch: IExpressionNode);
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TLambdaExpressionNode }
TLambdaExpressionNode = class(TAstNode, ILambdaExpressionNode)
private
FParameters: TArray<IIdentifierNode>;
FBody: IExpressionNode;
function GetParameters: TArray<IIdentifierNode>;
function GetBody: IExpressionNode;
public
constructor Create(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode);
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TFunctionCallNode }
TFunctionCallNode = class(TAstNode, IFunctionCallNode)
private
FCallee: IExpressionNode;
FArguments: TList<IExpressionNode>;
function GetCallee: IExpressionNode;
function GetArguments: TList<IExpressionNode>;
public
constructor Create(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode);
destructor Destroy; override;
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TBlockExpressionNode }
TBlockExpressionNode = class(TAstNode, IBlockExpressionNode)
private
FExpressions: TList<IExpressionNode>;
function GetExpressions: TList<IExpressionNode>;
public
constructor Create(const AExpressions: array of IExpressionNode);
destructor Destroy; override;
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TVariableDeclarationNode }
TVariableDeclarationNode = class(TAstNode, IVariableDeclarationNode)
private
FIdentifier: IIdentifierNode;
FInitializer: IExpressionNode;
function GetIdentifier: IIdentifierNode;
function GetInitializer: IExpressionNode;
public
constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode);
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TAssignmentNode }
TAssignmentNode = class(TAstNode, IAssignmentNode)
private
FIdentifier: IIdentifierNode;
FValue: IExpressionNode;
function GetIdentifier: IIdentifierNode;
function GetValue: IExpressionNode;
public
constructor Create(const AIdentifier: IIdentifierNode; const AValue: IExpressionNode);
function Accept(const Visitor: IAstVisitor): TAstValue; override;
end;
{ TConstantNode }
constructor TConstantNode.Create(AValue: TScalar);
begin
inherited Create;
FValue := AValue;
end;
function TConstantNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitConstant(Self);
end;
function TConstantNode.GetValue: TScalar;
begin
Result := FValue;
end;
{ TIdentifierNode }
constructor TIdentifierNode.Create(AName: string);
begin
inherited Create;
FName := AName;
end;
function TIdentifierNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitIdentifier(Self);
end;
function TIdentifierNode.GetName: string;
begin
Result := FName;
end;
{ TBinaryExpressionNode }
constructor TBinaryExpressionNode.Create(ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode);
begin
inherited Create;
FLeft := ALeft;
FOperator := AOperator;
FRight := ARight;
end;
function TBinaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitBinaryExpression(Self);
end;
function TBinaryExpressionNode.GetLeft: IExpressionNode;
begin
Result := FLeft;
end;
function TBinaryExpressionNode.GetOperator: TBinaryOperator;
begin
Result := FOperator;
end;
function TBinaryExpressionNode.GetRight: IExpressionNode;
begin
Result := FRight;
end;
{ TUnaryExpressionNode }
constructor TUnaryExpressionNode.Create(const AOperator: TUnaryOperator; const ARight: IExpressionNode);
begin
inherited Create;
FOperator := AOperator;
FRight := ARight;
end;
function TUnaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitUnaryExpression(Self);
end;
function TUnaryExpressionNode.GetOperator: TUnaryOperator;
begin
Result := FOperator;
end;
function TUnaryExpressionNode.GetRight: IExpressionNode;
begin
Result := FRight;
end;
{ TIfExpressionNode }
constructor TIfExpressionNode.Create(const ACondition, AThenBranch, AElseBranch: IExpressionNode);
begin
inherited Create;
FCondition := ACondition;
FThenBranch := AThenBranch;
FElseBranch := AElseBranch;
end;
function TIfExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitIfExpression(Self);
end;
function TIfExpressionNode.GetCondition: IExpressionNode;
begin
Result := FCondition;
end;
function TIfExpressionNode.GetElseBranch: IExpressionNode;
begin
Result := FElseBranch;
end;
function TIfExpressionNode.GetThenBranch: IExpressionNode;
begin
Result := FThenBranch;
end;
{ TLambdaExpressionNode }
constructor TLambdaExpressionNode.Create(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode);
begin
inherited Create;
FBody := ABody;
FParameters := AParameters;
end;
function TLambdaExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitLambdaExpression(Self);
end;
function TLambdaExpressionNode.GetBody: IExpressionNode;
begin
Result := FBody;
end;
function TLambdaExpressionNode.GetParameters: TArray<IIdentifierNode>;
begin
Result := FParameters;
end;
{ TFunctionCallNode }
constructor TFunctionCallNode.Create(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode);
var
arg: IExpressionNode;
begin
inherited Create;
FCallee := ACallee;
FArguments := TList<IExpressionNode>.Create;
for arg in AArguments do
FArguments.Add(arg);
end;
destructor TFunctionCallNode.Destroy;
begin
FArguments.Free;
inherited;
end;
function TFunctionCallNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitFunctionCall(Self);
end;
function TFunctionCallNode.GetArguments: TList<IExpressionNode>;
begin
Result := FArguments;
end;
function TFunctionCallNode.GetCallee: IExpressionNode;
begin
Result := FCallee;
end;
{ TBlockExpressionNode }
constructor TBlockExpressionNode.Create(const AExpressions: array of IExpressionNode);
var
expr: IExpressionNode;
begin
inherited Create;
FExpressions := TList<IExpressionNode>.Create;
for expr in AExpressions do
FExpressions.Add(expr);
end;
destructor TBlockExpressionNode.Destroy;
begin
FExpressions.Free;
inherited;
end;
function TBlockExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitBlockExpression(Self);
end;
function TBlockExpressionNode.GetExpressions: TList<IExpressionNode>;
begin
Result := FExpressions;
end;
{ TVariableDeclarationNode }
constructor TVariableDeclarationNode.Create(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode);
begin
inherited Create;
FIdentifier := AIdentifier;
FInitializer := AInitializer;
end;
function TVariableDeclarationNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitVariableDeclaration(Self);
end;
function TVariableDeclarationNode.GetIdentifier: IIdentifierNode;
begin
Result := FIdentifier;
end;
function TVariableDeclarationNode.GetInitializer: IExpressionNode;
begin
Result := FInitializer;
end;
{ TAssignmentNode }
constructor TAssignmentNode.Create(const AIdentifier: IIdentifierNode; const AValue: IExpressionNode);
begin
inherited Create;
FIdentifier := AIdentifier;
FValue := AValue;
end;
function TAssignmentNode.Accept(const Visitor: IAstVisitor): TAstValue;
begin
Result := Visitor.VisitAssignment(Self);
end;
function TAssignmentNode.GetIdentifier: IIdentifierNode;
begin
Result := FIdentifier;
end;
function TAssignmentNode.GetValue: IExpressionNode;
begin
Result := FValue;
end;
{ TAst }
class function TAst.Assign(const AIdentifier: IIdentifierNode; const AValue: IExpressionNode): IAssignmentNode;
begin
Result := TAssignmentNode.Create(AIdentifier, AValue);
end;
class function TAst.Block(const AExpressions: array of IExpressionNode): IBlockExpressionNode;
begin
Result := TBlockExpressionNode.Create(AExpressions);
end;
class function TAst.Constant(AValue: TScalar): IConstantNode;
begin
Result := TConstantNode.Create(AValue);
end;
class function TAst.BinaryExpr(ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode): IBinaryExpressionNode;
begin
Result := TBinaryExpressionNode.Create(ALeft, AOperator, ARight);
end;
class function TAst.FunctionCall(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode): 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: IExpressionNode; const AThenBranch, AElseBranch: IExpressionNode): IIfExpressionNode;
begin
Result := TIfExpressionNode.Create(ACondition, AThenBranch, AElseBranch);
end;
class function TAst.LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode): ILambdaExpressionNode;
begin
Result := TLambdaExpressionNode.Create(AParameters, ABody);
end;
class function TAst.UnaryExpr(const AOperator: TUnaryOperator; const ARight: IExpressionNode): IUnaryExpressionNode;
begin
Result := TUnaryExpressionNode.Create(AOperator, ARight);
end;
class function TAst.VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode): IVariableDeclarationNode;
begin
Result := TVariableDeclarationNode.Create(AIdentifier, AInitializer);
end;
end.