AST refactoring
This commit is contained in:
+463
-248
@@ -4,8 +4,9 @@ interface
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.Classes,
|
||||
System.Generics.Collections,
|
||||
Myc.Data.Types;
|
||||
Myc.Data.POD;
|
||||
|
||||
type
|
||||
// Operators are now type-safe enums
|
||||
@@ -21,12 +22,19 @@ type
|
||||
function ToString: string;
|
||||
end;
|
||||
|
||||
// Forward declarations for interfaces
|
||||
// Defines the kind of value stored in a TAstValue record.
|
||||
TAstValueKind = (
|
||||
avkUndefined, // Represents a void, null or uninitialized value.
|
||||
avkScalar, // The value is a POD scalar (TScalar).
|
||||
avkClosure // The value is a managed closure (IEvaluatorClosure).
|
||||
);
|
||||
|
||||
// --- Forward Declarations to break cycles ---
|
||||
IAstVisitor = interface;
|
||||
IAstNode = interface;
|
||||
IExpressionNode = interface;
|
||||
IConstantNode = interface;
|
||||
IIdentifierNode = interface;
|
||||
IConstantNode = interface;
|
||||
IBinaryExpressionNode = interface;
|
||||
IUnaryExpressionNode = interface;
|
||||
IIfExpressionNode = interface;
|
||||
@@ -34,27 +42,85 @@ type
|
||||
IFunctionCallNode = interface;
|
||||
IBlockExpressionNode = interface;
|
||||
IVariableDeclarationNode = interface;
|
||||
IEvaluatorClosure = interface;
|
||||
TExecutionScope = class;
|
||||
|
||||
// --- Abstract Node Interfaces ---
|
||||
// --- Concrete Type Definitions ---
|
||||
|
||||
// Base interface for all AST nodes
|
||||
// Represents a closure value for the TAstValue-based evaluator.
|
||||
IEvaluatorClosure = interface(IInterface)
|
||||
{$region 'private'}
|
||||
function GetBody: IExpressionNode;
|
||||
function GetParameters: TList<IIdentifierNode>;
|
||||
function GetClosureScope: TExecutionScope;
|
||||
{$endregion}
|
||||
property Body: IExpressionNode read GetBody;
|
||||
property Parameters: TList<IIdentifierNode> read GetParameters;
|
||||
property ClosureScope: TExecutionScope read GetClosureScope;
|
||||
end;
|
||||
|
||||
// A universal value container for the AST evaluator.
|
||||
TAstValue = record
|
||||
private
|
||||
FKind: TAstValueKind;
|
||||
FScalar: TScalar;
|
||||
FClosure: IEvaluatorClosure;
|
||||
|
||||
function GetKind: TAstValueKind; inline;
|
||||
function GetIsScalar: Boolean; inline;
|
||||
function GetIsClosure: Boolean; inline;
|
||||
function GetIsUndefined: Boolean; inline;
|
||||
public
|
||||
// Managed record operators to handle the lifetime of FObject.
|
||||
class operator Initialize(out Dest: TAstValue);
|
||||
// Factory methods for clean creation.
|
||||
class function Undefined: TAstValue; static;
|
||||
class function FromScalar(const AValue: TScalar): TAstValue; static;
|
||||
class function FromClosure(const AValue: IEvaluatorClosure): TAstValue; static;
|
||||
|
||||
// Accessors for the stored values.
|
||||
function AsScalar: TScalar;
|
||||
function AsClosure: IEvaluatorClosure;
|
||||
|
||||
function ToString: String;
|
||||
|
||||
// Properties for convenient access and type checking.
|
||||
property Kind: TAstValueKind read GetKind;
|
||||
property IsScalar: Boolean read GetIsScalar;
|
||||
property IsClosure: Boolean read GetIsClosure;
|
||||
property IsUndefined: Boolean read GetIsUndefined;
|
||||
end;
|
||||
|
||||
// The visitor pattern interface for traversing the AST.
|
||||
IAstVisitor = interface
|
||||
['{A58B0A8E-F438-4217-A964-6E35624A9A4A}']
|
||||
function VisitConstant(const Node: IConstantNode): TAstValue;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): TAstValue;
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TAstValue;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue;
|
||||
end;
|
||||
|
||||
// --- AST Node Interfaces (now using TAstValue) ---
|
||||
|
||||
// Base interface for all AST nodes.
|
||||
IAstNode = interface(IInterface)
|
||||
// Accept is a function that returns the result of the visit.
|
||||
function Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
end;
|
||||
|
||||
// Abstract interface for all nodes that evaluate to a value.
|
||||
// In this paradigm, all nodes are expressions.
|
||||
IExpressionNode = interface(IAstNode)
|
||||
end;
|
||||
|
||||
// --- Concrete Expression Node Interfaces ---
|
||||
|
||||
IConstantNode = interface(IExpressionNode)
|
||||
{$region 'private'}
|
||||
function GetValue: IDataValue;
|
||||
function GetValue: TScalar;
|
||||
{$endregion}
|
||||
property Value: IDataValue read GetValue;
|
||||
property Value: TScalar read GetValue;
|
||||
end;
|
||||
|
||||
IIdentifierNode = interface(IExpressionNode)
|
||||
@@ -98,7 +164,7 @@ type
|
||||
ILambdaExpressionNode = interface(IExpressionNode)
|
||||
{$region 'private'}
|
||||
function GetParameters: TList<IIdentifierNode>;
|
||||
function GetBody: IExpressionNode; // Body is now always an expression
|
||||
function GetBody: IExpressionNode;
|
||||
{$endregion}
|
||||
property Parameters: TList<IIdentifierNode> read GetParameters;
|
||||
property Body: IExpressionNode read GetBody;
|
||||
@@ -121,7 +187,7 @@ type
|
||||
property Expressions: TList<IExpressionNode> read GetExpressions;
|
||||
end;
|
||||
|
||||
// A variable declaration is an expression that returns a void value.
|
||||
// A variable declaration is an expression that returns an undefined value.
|
||||
IVariableDeclarationNode = interface(IExpressionNode)
|
||||
{$region 'private'}
|
||||
function GetIdentifier: IIdentifierNode;
|
||||
@@ -131,23 +197,9 @@ type
|
||||
property Initializer: IExpressionNode read GetInitializer;
|
||||
end;
|
||||
|
||||
// All visitor methods are functions returning a value.
|
||||
IAstVisitor = interface
|
||||
['{5F4110E9-0158-41E9-A512-E57A843E8A5A}']
|
||||
function VisitConstant(const Node: IConstantNode): IDataValue;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): IDataValue;
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): IDataValue;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): IDataValue;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): IDataValue;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IDataValue;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): IDataValue;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): IDataValue;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IDataValue;
|
||||
end;
|
||||
|
||||
// Record acting as a namespace for the factory functions.
|
||||
TAst = record
|
||||
class function Constant(AValue: IDataValue): IConstantNode; static;
|
||||
class function Constant(AValue: TScalar): IConstantNode; static;
|
||||
class function Identifier(AName: string): IIdentifierNode; static;
|
||||
class function BinaryExpr(
|
||||
ALeft: IExpressionNode;
|
||||
@@ -165,8 +217,212 @@ type
|
||||
class function VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode): IVariableDeclarationNode; static;
|
||||
end;
|
||||
|
||||
// Manages the scope of execution, holding variables and their values.
|
||||
TExecutionScope = class
|
||||
private
|
||||
FParent: TExecutionScope;
|
||||
FVariables: TDictionary<string, TAstValue>;
|
||||
procedure DumpScope(const ABuilder: TStringBuilder; AIndent: Integer);
|
||||
public
|
||||
constructor Create(AParent: TExecutionScope = nil);
|
||||
destructor Destroy; override;
|
||||
function FindValue(const Name: string; out Value: TAstValue): Boolean;
|
||||
procedure SetValue(const Name: string; const Value: TAstValue);
|
||||
function Dump: string;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
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: TList<IIdentifierNode>;
|
||||
FBody: IExpressionNode;
|
||||
function GetParameters: TList<IIdentifierNode>;
|
||||
function GetBody: IExpressionNode;
|
||||
public
|
||||
constructor Create(const AParameters: array of IIdentifierNode; const ABody: IExpressionNode);
|
||||
destructor Destroy; override;
|
||||
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;
|
||||
|
||||
{ TAstValue }
|
||||
|
||||
class operator TAstValue.Initialize(out Dest: TAstValue);
|
||||
begin
|
||||
// Ensures the record is in a clean state when created.
|
||||
Dest.FKind := avkUndefined;
|
||||
end;
|
||||
|
||||
function TAstValue.AsClosure: IEvaluatorClosure;
|
||||
begin
|
||||
if (FKind <> avkClosure) then
|
||||
raise EInvalidCast.Create('Cannot read value as a Closure.');
|
||||
Result := FClosure;
|
||||
end;
|
||||
|
||||
function TAstValue.AsScalar: TScalar;
|
||||
begin
|
||||
if (FKind <> avkScalar) then
|
||||
raise EInvalidCast.Create('Cannot read value as a Scalar.');
|
||||
Result := FScalar;
|
||||
end;
|
||||
|
||||
class function TAstValue.FromClosure(const AValue: IEvaluatorClosure): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkClosure;
|
||||
Result.FClosure := AValue;
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
|
||||
class function TAstValue.FromScalar(const AValue: TScalar): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkScalar;
|
||||
Result.FScalar := AValue;
|
||||
Result.FClosure := nil;
|
||||
end;
|
||||
|
||||
function TAstValue.GetIsClosure: Boolean;
|
||||
begin
|
||||
Result := FKind = avkClosure;
|
||||
end;
|
||||
|
||||
function TAstValue.GetIsScalar: Boolean;
|
||||
begin
|
||||
Result := FKind = avkScalar;
|
||||
end;
|
||||
|
||||
function TAstValue.GetIsUndefined: Boolean;
|
||||
begin
|
||||
Result := FKind = avkUndefined;
|
||||
end;
|
||||
|
||||
function TAstValue.GetKind: TAstValueKind;
|
||||
begin
|
||||
Result := FKind;
|
||||
end;
|
||||
|
||||
function TAstValue.ToString: String;
|
||||
begin
|
||||
case FKind of
|
||||
avkScalar: Result := FScalar.ToString;
|
||||
avkClosure: Result := '<closure>';
|
||||
avkUndefined: Result := '<void>';
|
||||
else
|
||||
Result := '[Unknown AstValue]';
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TAstValue.Undefined: TAstValue;
|
||||
begin
|
||||
// Returns a default-initialized record, which is avkUndefined.
|
||||
Result := Default(TAstValue);
|
||||
end;
|
||||
|
||||
{ TBinaryOperatorHelper }
|
||||
|
||||
function TBinaryOperatorHelper.ToString: string;
|
||||
@@ -199,211 +455,45 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
type
|
||||
TConstantNodeImpl = class(TInterfacedObject, IConstantNode)
|
||||
private
|
||||
FValue: IDataValue;
|
||||
function GetValue: IDataValue;
|
||||
public
|
||||
constructor Create(AValue: IDataValue);
|
||||
function Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
end;
|
||||
{ TConstantNode }
|
||||
|
||||
TIdentifierNodeImpl = class(TInterfacedObject, IIdentifierNode)
|
||||
private
|
||||
FName: string;
|
||||
function GetName: string;
|
||||
public
|
||||
constructor Create(AName: string);
|
||||
function Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
end;
|
||||
|
||||
TBinaryExpressionNodeImpl = class(TInterfacedObject, 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): IDataValue;
|
||||
end;
|
||||
|
||||
TUnaryExpressionNodeImpl = class(TInterfacedObject, IUnaryExpressionNode)
|
||||
private
|
||||
FOperator: TUnaryOperator;
|
||||
FRight: IExpressionNode;
|
||||
function GetOperator: TUnaryOperator;
|
||||
function GetRight: IExpressionNode;
|
||||
public
|
||||
constructor Create(AOperator: TUnaryOperator; ARight: IExpressionNode);
|
||||
function Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
end;
|
||||
|
||||
TIfExpressionNodeImpl = class(TInterfacedObject, IIfExpressionNode)
|
||||
private
|
||||
FCondition: IExpressionNode;
|
||||
FThenBranch: IExpressionNode;
|
||||
FElseBranch: IExpressionNode;
|
||||
function GetCondition: IExpressionNode;
|
||||
function GetThenBranch: IExpressionNode;
|
||||
function GetElseBranch: IExpressionNode;
|
||||
public
|
||||
constructor Create(ACondition, AThenBranch, AElseBranch: IExpressionNode);
|
||||
function Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
end;
|
||||
|
||||
TLambdaExpressionNodeImpl = class(TInterfacedObject, ILambdaExpressionNode)
|
||||
private
|
||||
FParameters: TList<IIdentifierNode>;
|
||||
FBody: IExpressionNode;
|
||||
function GetParameters: TList<IIdentifierNode>;
|
||||
function GetBody: IExpressionNode;
|
||||
public
|
||||
constructor Create(AParameters: TList<IIdentifierNode>; ABody: IExpressionNode);
|
||||
destructor Destroy; override;
|
||||
function Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
end;
|
||||
|
||||
TFunctionCallNodeImpl = class(TInterfacedObject, IFunctionCallNode)
|
||||
private
|
||||
FCallee: IExpressionNode;
|
||||
FArguments: TList<IExpressionNode>;
|
||||
function GetCallee: IExpressionNode;
|
||||
function GetArguments: TList<IExpressionNode>;
|
||||
public
|
||||
constructor Create(ACallee: IExpressionNode; AArguments: TList<IExpressionNode>);
|
||||
destructor Destroy; override;
|
||||
function Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
end;
|
||||
|
||||
TBlockExpressionNodeImpl = class(TInterfacedObject, IBlockExpressionNode)
|
||||
private
|
||||
FExpressions: TList<IExpressionNode>;
|
||||
function GetExpressions: TList<IExpressionNode>;
|
||||
public
|
||||
constructor Create(AExpressions: TList<IExpressionNode>);
|
||||
destructor Destroy; override;
|
||||
function Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
end;
|
||||
|
||||
TVariableDeclarationNodeImpl = class(TInterfacedObject, IVariableDeclarationNode)
|
||||
private
|
||||
FIdentifier: IIdentifierNode;
|
||||
FInitializer: IExpressionNode;
|
||||
function GetIdentifier: IIdentifierNode;
|
||||
function GetInitializer: IExpressionNode;
|
||||
public
|
||||
constructor Create(AIdentifier: IIdentifierNode; AInitializer: IExpressionNode);
|
||||
function Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
end;
|
||||
|
||||
{ TAst - Factory Function Implementations }
|
||||
|
||||
class function TAst.Constant(AValue: IDataValue): IConstantNode;
|
||||
begin
|
||||
Result := TConstantNodeImpl.Create(AValue);
|
||||
end;
|
||||
|
||||
class function TAst.Identifier(AName: string): IIdentifierNode;
|
||||
begin
|
||||
Result := TIdentifierNodeImpl.Create(AName);
|
||||
end;
|
||||
|
||||
class function TAst.BinaryExpr(ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode): IBinaryExpressionNode;
|
||||
begin
|
||||
Result := TBinaryExpressionNodeImpl.Create(ALeft, AOperator, ARight);
|
||||
end;
|
||||
|
||||
class function TAst.UnaryExpr(const AOperator: TUnaryOperator; const ARight: IExpressionNode): IUnaryExpressionNode;
|
||||
begin
|
||||
Result := TUnaryExpressionNodeImpl.Create(AOperator, ARight);
|
||||
end;
|
||||
|
||||
class function TAst.IfExpr(const ACondition: IExpressionNode; const AThenBranch, AElseBranch: IExpressionNode): IIfExpressionNode;
|
||||
begin
|
||||
Result := TIfExpressionNodeImpl.Create(ACondition, AThenBranch, AElseBranch);
|
||||
end;
|
||||
|
||||
class function TAst.LambdaExpr(const AParameters: array of IIdentifierNode; const ABody: IExpressionNode): ILambdaExpressionNode;
|
||||
var
|
||||
paramList: TList<IIdentifierNode>;
|
||||
param: IIdentifierNode;
|
||||
begin
|
||||
paramList := TList<IIdentifierNode>.Create;
|
||||
for param in AParameters do
|
||||
paramList.Add(param);
|
||||
Result := TLambdaExpressionNodeImpl.Create(paramList, ABody);
|
||||
end;
|
||||
|
||||
class function TAst.FunctionCall(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode): IFunctionCallNode;
|
||||
var
|
||||
argList: TList<IExpressionNode>;
|
||||
arg: IExpressionNode;
|
||||
begin
|
||||
argList := TList<IExpressionNode>.Create;
|
||||
for arg in AArguments do
|
||||
argList.Add(arg);
|
||||
Result := TFunctionCallNodeImpl.Create(ACallee, argList);
|
||||
end;
|
||||
|
||||
class function TAst.Block(const AExpressions: array of IExpressionNode): IBlockExpressionNode;
|
||||
var
|
||||
exprList: TList<IExpressionNode>;
|
||||
expr: IExpressionNode;
|
||||
begin
|
||||
exprList := TList<IExpressionNode>.Create;
|
||||
for expr in AExpressions do
|
||||
exprList.Add(expr);
|
||||
Result := TBlockExpressionNodeImpl.Create(exprList);
|
||||
end;
|
||||
|
||||
class function TAst.VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode): IVariableDeclarationNode;
|
||||
begin
|
||||
Result := TVariableDeclarationNodeImpl.Create(AIdentifier, AInitializer);
|
||||
end;
|
||||
|
||||
{ TConstantNodeImpl }
|
||||
|
||||
constructor TConstantNodeImpl.Create(AValue: IDataValue);
|
||||
constructor TConstantNode.Create(AValue: TScalar);
|
||||
begin
|
||||
inherited Create;
|
||||
FValue := AValue;
|
||||
end;
|
||||
|
||||
function TConstantNodeImpl.Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function TConstantNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitConstant(Self);
|
||||
end;
|
||||
|
||||
function TConstantNodeImpl.GetValue: IDataValue;
|
||||
function TConstantNode.GetValue: TScalar;
|
||||
begin
|
||||
Result := FValue;
|
||||
end;
|
||||
|
||||
{ TIdentifierNodeImpl }
|
||||
{ TIdentifierNode }
|
||||
|
||||
constructor TIdentifierNodeImpl.Create(AName: string);
|
||||
constructor TIdentifierNode.Create(AName: string);
|
||||
begin
|
||||
inherited Create;
|
||||
FName := AName;
|
||||
end;
|
||||
|
||||
function TIdentifierNodeImpl.Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function TIdentifierNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitIdentifier(Self);
|
||||
end;
|
||||
|
||||
function TIdentifierNodeImpl.GetName: string;
|
||||
function TIdentifierNode.GetName: string;
|
||||
begin
|
||||
Result := FName;
|
||||
end;
|
||||
|
||||
{ TBinaryExpressionNodeImpl }
|
||||
{ TBinaryExpressionNode }
|
||||
|
||||
constructor TBinaryExpressionNodeImpl.Create(ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode);
|
||||
constructor TBinaryExpressionNode.Create(ALeft: IExpressionNode; AOperator: TBinaryOperator; ARight: IExpressionNode);
|
||||
begin
|
||||
inherited Create;
|
||||
FLeft := ALeft;
|
||||
@@ -411,53 +501,53 @@ begin
|
||||
FRight := ARight;
|
||||
end;
|
||||
|
||||
function TBinaryExpressionNodeImpl.Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function TBinaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitBinaryExpression(Self);
|
||||
end;
|
||||
|
||||
function TBinaryExpressionNodeImpl.GetLeft: IExpressionNode;
|
||||
function TBinaryExpressionNode.GetLeft: IExpressionNode;
|
||||
begin
|
||||
Result := FLeft;
|
||||
end;
|
||||
|
||||
function TBinaryExpressionNodeImpl.GetOperator: TBinaryOperator;
|
||||
function TBinaryExpressionNode.GetOperator: TBinaryOperator;
|
||||
begin
|
||||
Result := FOperator;
|
||||
end;
|
||||
|
||||
function TBinaryExpressionNodeImpl.GetRight: IExpressionNode;
|
||||
function TBinaryExpressionNode.GetRight: IExpressionNode;
|
||||
begin
|
||||
Result := FRight;
|
||||
end;
|
||||
|
||||
{ TUnaryExpressionNodeImpl }
|
||||
{ TUnaryExpressionNode }
|
||||
|
||||
constructor TUnaryExpressionNodeImpl.Create(AOperator: TUnaryOperator; ARight: IExpressionNode);
|
||||
constructor TUnaryExpressionNode.Create(const AOperator: TUnaryOperator; const ARight: IExpressionNode);
|
||||
begin
|
||||
inherited Create;
|
||||
FOperator := AOperator;
|
||||
FRight := ARight;
|
||||
end;
|
||||
|
||||
function TUnaryExpressionNodeImpl.Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function TUnaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitUnaryExpression(Self);
|
||||
end;
|
||||
|
||||
function TUnaryExpressionNodeImpl.GetOperator: TUnaryOperator;
|
||||
function TUnaryExpressionNode.GetOperator: TUnaryOperator;
|
||||
begin
|
||||
Result := FOperator;
|
||||
end;
|
||||
|
||||
function TUnaryExpressionNodeImpl.GetRight: IExpressionNode;
|
||||
function TUnaryExpressionNode.GetRight: IExpressionNode;
|
||||
begin
|
||||
Result := FRight;
|
||||
end;
|
||||
|
||||
{ TIfExpressionNodeImpl }
|
||||
{ TIfExpressionNode }
|
||||
|
||||
constructor TIfExpressionNodeImpl.Create(ACondition, AThenBranch, AElseBranch: IExpressionNode);
|
||||
constructor TIfExpressionNode.Create(const ACondition, AThenBranch, AElseBranch: IExpressionNode);
|
||||
begin
|
||||
inherited Create;
|
||||
FCondition := ACondition;
|
||||
@@ -465,132 +555,257 @@ begin
|
||||
FElseBranch := AElseBranch;
|
||||
end;
|
||||
|
||||
function TIfExpressionNodeImpl.Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function TIfExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitIfExpression(Self);
|
||||
end;
|
||||
|
||||
function TIfExpressionNodeImpl.GetCondition: IExpressionNode;
|
||||
function TIfExpressionNode.GetCondition: IExpressionNode;
|
||||
begin
|
||||
Result := FCondition;
|
||||
end;
|
||||
|
||||
function TIfExpressionNodeImpl.GetElseBranch: IExpressionNode;
|
||||
function TIfExpressionNode.GetElseBranch: IExpressionNode;
|
||||
begin
|
||||
Result := FElseBranch;
|
||||
end;
|
||||
|
||||
function TIfExpressionNodeImpl.GetThenBranch: IExpressionNode;
|
||||
function TIfExpressionNode.GetThenBranch: IExpressionNode;
|
||||
begin
|
||||
Result := FThenBranch;
|
||||
end;
|
||||
|
||||
{ TLambdaExpressionNodeImpl }
|
||||
{ TLambdaExpressionNode }
|
||||
|
||||
constructor TLambdaExpressionNodeImpl.Create(AParameters: TList<IIdentifierNode>; ABody: IExpressionNode);
|
||||
constructor TLambdaExpressionNode.Create(const AParameters: array of IIdentifierNode; const ABody: IExpressionNode);
|
||||
var
|
||||
param: IIdentifierNode;
|
||||
begin
|
||||
inherited Create;
|
||||
FParameters := AParameters;
|
||||
FBody := ABody;
|
||||
FParameters := TList<IIdentifierNode>.Create;
|
||||
for param in AParameters do
|
||||
FParameters.Add(param);
|
||||
end;
|
||||
|
||||
destructor TLambdaExpressionNodeImpl.Destroy;
|
||||
destructor TLambdaExpressionNode.Destroy;
|
||||
begin
|
||||
FParameters.Free;
|
||||
inherited Destroy;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TLambdaExpressionNodeImpl.Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function TLambdaExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitLambdaExpression(Self);
|
||||
end;
|
||||
|
||||
function TLambdaExpressionNodeImpl.GetBody: IExpressionNode;
|
||||
function TLambdaExpressionNode.GetBody: IExpressionNode;
|
||||
begin
|
||||
Result := FBody;
|
||||
end;
|
||||
|
||||
function TLambdaExpressionNodeImpl.GetParameters: TList<IIdentifierNode>;
|
||||
function TLambdaExpressionNode.GetParameters: TList<IIdentifierNode>;
|
||||
begin
|
||||
Result := FParameters;
|
||||
end;
|
||||
|
||||
{ TFunctionCallNodeImpl }
|
||||
{ TFunctionCallNode }
|
||||
|
||||
constructor TFunctionCallNodeImpl.Create(ACallee: IExpressionNode; AArguments: TList<IExpressionNode>);
|
||||
constructor TFunctionCallNode.Create(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode);
|
||||
var
|
||||
arg: IExpressionNode;
|
||||
begin
|
||||
inherited Create;
|
||||
FCallee := ACallee;
|
||||
FArguments := AArguments;
|
||||
FArguments := TList<IExpressionNode>.Create;
|
||||
for arg in AArguments do
|
||||
FArguments.Add(arg);
|
||||
end;
|
||||
|
||||
destructor TFunctionCallNodeImpl.Destroy;
|
||||
destructor TFunctionCallNode.Destroy;
|
||||
begin
|
||||
FArguments.Free;
|
||||
inherited Destroy;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TFunctionCallNodeImpl.Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function TFunctionCallNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitFunctionCall(Self);
|
||||
end;
|
||||
|
||||
function TFunctionCallNodeImpl.GetArguments: TList<IExpressionNode>;
|
||||
function TFunctionCallNode.GetArguments: TList<IExpressionNode>;
|
||||
begin
|
||||
Result := FArguments;
|
||||
end;
|
||||
|
||||
function TFunctionCallNodeImpl.GetCallee: IExpressionNode;
|
||||
function TFunctionCallNode.GetCallee: IExpressionNode;
|
||||
begin
|
||||
Result := FCallee;
|
||||
end;
|
||||
|
||||
{ TBlockExpressionNodeImpl }
|
||||
{ TBlockExpressionNode }
|
||||
|
||||
constructor TBlockExpressionNodeImpl.Create(AExpressions: TList<IExpressionNode>);
|
||||
constructor TBlockExpressionNode.Create(const AExpressions: array of IExpressionNode);
|
||||
var
|
||||
expr: IExpressionNode;
|
||||
begin
|
||||
inherited Create;
|
||||
FExpressions := AExpressions;
|
||||
FExpressions := TList<IExpressionNode>.Create;
|
||||
for expr in AExpressions do
|
||||
FExpressions.Add(expr);
|
||||
end;
|
||||
|
||||
destructor TBlockExpressionNodeImpl.Destroy;
|
||||
destructor TBlockExpressionNode.Destroy;
|
||||
begin
|
||||
FExpressions.Free;
|
||||
inherited Destroy;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TBlockExpressionNodeImpl.Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function TBlockExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitBlockExpression(Self);
|
||||
end;
|
||||
|
||||
function TBlockExpressionNodeImpl.GetExpressions: TList<IExpressionNode>;
|
||||
function TBlockExpressionNode.GetExpressions: TList<IExpressionNode>;
|
||||
begin
|
||||
Result := FExpressions;
|
||||
end;
|
||||
|
||||
{ TVariableDeclarationNodeImpl }
|
||||
{ TVariableDeclarationNode }
|
||||
|
||||
constructor TVariableDeclarationNodeImpl.Create(AIdentifier: IIdentifierNode; AInitializer: IExpressionNode);
|
||||
constructor TVariableDeclarationNode.Create(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode);
|
||||
begin
|
||||
inherited Create;
|
||||
FIdentifier := AIdentifier;
|
||||
FInitializer := AInitializer;
|
||||
end;
|
||||
|
||||
function TVariableDeclarationNodeImpl.Accept(const Visitor: IAstVisitor): IDataValue;
|
||||
function TVariableDeclarationNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitVariableDeclaration(Self);
|
||||
end;
|
||||
|
||||
function TVariableDeclarationNodeImpl.GetIdentifier: IIdentifierNode;
|
||||
function TVariableDeclarationNode.GetIdentifier: IIdentifierNode;
|
||||
begin
|
||||
Result := FIdentifier;
|
||||
end;
|
||||
|
||||
function TVariableDeclarationNodeImpl.GetInitializer: IExpressionNode;
|
||||
function TVariableDeclarationNode.GetInitializer: IExpressionNode;
|
||||
begin
|
||||
Result := FInitializer;
|
||||
end;
|
||||
|
||||
{ TAst }
|
||||
|
||||
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: array of 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;
|
||||
|
||||
{ TExecutionScope }
|
||||
|
||||
constructor TExecutionScope.Create(AParent: TExecutionScope);
|
||||
begin
|
||||
inherited Create;
|
||||
FParent := AParent;
|
||||
FVariables := TDictionary<string, TAstValue>.Create;
|
||||
end;
|
||||
|
||||
destructor TExecutionScope.Destroy;
|
||||
begin
|
||||
FVariables.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TExecutionScope.DumpScope(const ABuilder: TStringBuilder; AIndent: Integer);
|
||||
var
|
||||
pair: TPair<string, TAstValue>;
|
||||
indentStr: string;
|
||||
begin
|
||||
indentStr := ''.PadLeft(AIndent);
|
||||
if (FVariables.Count > 0) then
|
||||
begin
|
||||
for pair in FVariables do
|
||||
ABuilder.AppendLine(indentStr + Format(' %s: %s', [pair.Key, pair.Value.ToString]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
ABuilder.AppendLine(indentStr + ' (empty)');
|
||||
end;
|
||||
|
||||
if Assigned(FParent) then
|
||||
begin
|
||||
ABuilder.AppendLine(indentStr + '[Parent Scope]');
|
||||
FParent.DumpScope(ABuilder, AIndent + 2);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TExecutionScope.Dump: string;
|
||||
var
|
||||
builder: TStringBuilder;
|
||||
begin
|
||||
builder := TStringBuilder.Create;
|
||||
try
|
||||
builder.AppendLine('[Current Scope]');
|
||||
DumpScope(builder, 0);
|
||||
Result := builder.ToString.TrimRight;
|
||||
finally
|
||||
builder.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TExecutionScope.FindValue(const Name: string; out Value: TAstValue): Boolean;
|
||||
begin
|
||||
Result := FVariables.TryGetValue(Name, Value);
|
||||
if not Result and Assigned(FParent) then
|
||||
begin
|
||||
Result := FParent.FindValue(Name, Value);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TExecutionScope.SetValue(const Name: string; const Value: TAstValue);
|
||||
begin
|
||||
FVariables.AddOrSetValue(Name, Value);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user