AST refactoring
This commit is contained in:
+87
-23
@@ -42,6 +42,7 @@ type
|
||||
IFunctionCallNode = interface;
|
||||
IBlockExpressionNode = interface;
|
||||
IVariableDeclarationNode = interface;
|
||||
IAssignmentNode = interface; // Represents an assignment to an existing variable.
|
||||
IEvaluatorClosure = interface;
|
||||
TExecutionScope = class;
|
||||
|
||||
@@ -51,11 +52,11 @@ type
|
||||
IEvaluatorClosure = interface(IInterface)
|
||||
{$region 'private'}
|
||||
function GetBody: IExpressionNode;
|
||||
function GetParameters: TList<IIdentifierNode>;
|
||||
function GetParameters: TArray<IIdentifierNode>;
|
||||
function GetClosureScope: TExecutionScope;
|
||||
{$endregion}
|
||||
property Body: IExpressionNode read GetBody;
|
||||
property Parameters: TList<IIdentifierNode> read GetParameters;
|
||||
property Parameters: TArray<IIdentifierNode> read GetParameters;
|
||||
property ClosureScope: TExecutionScope read GetClosureScope;
|
||||
end;
|
||||
|
||||
@@ -103,6 +104,7 @@ type
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue;
|
||||
function VisitAssignment(const Node: IAssignmentNode): TAstValue;
|
||||
end;
|
||||
|
||||
// --- AST Node Interfaces (now using TAstValue) ---
|
||||
@@ -163,10 +165,10 @@ type
|
||||
|
||||
ILambdaExpressionNode = interface(IExpressionNode)
|
||||
{$region 'private'}
|
||||
function GetParameters: TList<IIdentifierNode>;
|
||||
function GetParameters: TArray<IIdentifierNode>;
|
||||
function GetBody: IExpressionNode;
|
||||
{$endregion}
|
||||
property Parameters: TList<IIdentifierNode> read GetParameters;
|
||||
property Parameters: TArray<IIdentifierNode> read GetParameters;
|
||||
property Body: IExpressionNode read GetBody;
|
||||
end;
|
||||
|
||||
@@ -197,6 +199,16 @@ type
|
||||
property Initializer: IExpressionNode read GetInitializer;
|
||||
end;
|
||||
|
||||
// An assignment expression that returns the assigned value.
|
||||
IAssignmentNode = interface(IExpressionNode)
|
||||
{$region 'private'}
|
||||
function GetIdentifier: IIdentifierNode;
|
||||
function GetValue: IExpressionNode;
|
||||
{$endregion}
|
||||
property Identifier: IIdentifierNode read GetIdentifier;
|
||||
property Value: IExpressionNode read GetValue;
|
||||
end;
|
||||
|
||||
// Record acting as a namespace for the factory functions.
|
||||
TAst = record
|
||||
class function Constant(AValue: TScalar): IConstantNode; static;
|
||||
@@ -211,10 +223,11 @@ type
|
||||
const ACondition: IExpressionNode;
|
||||
const AThenBranch, AElseBranch: IExpressionNode
|
||||
): IIfExpressionNode; static;
|
||||
class function LambdaExpr(const AParameters: array of IIdentifierNode; const ABody: IExpressionNode): ILambdaExpressionNode; 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;
|
||||
|
||||
// Manages the scope of execution, holding variables and their values.
|
||||
@@ -226,8 +239,12 @@ type
|
||||
public
|
||||
constructor Create(AParent: TExecutionScope = nil);
|
||||
destructor Destroy; override;
|
||||
procedure Clear;
|
||||
function FindValue(const Name: string; out Value: TAstValue): Boolean;
|
||||
// Sets or updates a value in the current scope. Used for declarations.
|
||||
procedure SetValue(const Name: string; const Value: TAstValue);
|
||||
// Finds an existing variable in the scope chain and updates its value. Used for assignments.
|
||||
procedure AssignValue(const Name: string; const Value: TAstValue);
|
||||
function Dump: string;
|
||||
end;
|
||||
|
||||
@@ -304,13 +321,12 @@ type
|
||||
{ TLambdaExpressionNode }
|
||||
TLambdaExpressionNode = class(TAstNode, ILambdaExpressionNode)
|
||||
private
|
||||
FParameters: TList<IIdentifierNode>;
|
||||
FParameters: TArray<IIdentifierNode>;
|
||||
FBody: IExpressionNode;
|
||||
function GetParameters: TList<IIdentifierNode>;
|
||||
function GetParameters: TArray<IIdentifierNode>;
|
||||
function GetBody: IExpressionNode;
|
||||
public
|
||||
constructor Create(const AParameters: array of IIdentifierNode; const ABody: IExpressionNode);
|
||||
destructor Destroy; override;
|
||||
constructor Create(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode);
|
||||
function Accept(const Visitor: IAstVisitor): TAstValue; override;
|
||||
end;
|
||||
|
||||
@@ -350,6 +366,18 @@ type
|
||||
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;
|
||||
|
||||
{ TAstValue }
|
||||
|
||||
class operator TAstValue.Initialize(out Dest: TAstValue);
|
||||
@@ -577,21 +605,11 @@ end;
|
||||
|
||||
{ TLambdaExpressionNode }
|
||||
|
||||
constructor TLambdaExpressionNode.Create(const AParameters: array of IIdentifierNode; const ABody: IExpressionNode);
|
||||
var
|
||||
param: IIdentifierNode;
|
||||
constructor TLambdaExpressionNode.Create(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode);
|
||||
begin
|
||||
inherited Create;
|
||||
FBody := ABody;
|
||||
FParameters := TList<IIdentifierNode>.Create;
|
||||
for param in AParameters do
|
||||
FParameters.Add(param);
|
||||
end;
|
||||
|
||||
destructor TLambdaExpressionNode.Destroy;
|
||||
begin
|
||||
FParameters.Free;
|
||||
inherited;
|
||||
FParameters := AParameters;
|
||||
end;
|
||||
|
||||
function TLambdaExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
@@ -604,7 +622,7 @@ begin
|
||||
Result := FBody;
|
||||
end;
|
||||
|
||||
function TLambdaExpressionNode.GetParameters: TList<IIdentifierNode>;
|
||||
function TLambdaExpressionNode.GetParameters: TArray<IIdentifierNode>;
|
||||
begin
|
||||
Result := FParameters;
|
||||
end;
|
||||
@@ -695,8 +713,37 @@ 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);
|
||||
@@ -727,7 +774,7 @@ begin
|
||||
Result := TIfExpressionNode.Create(ACondition, AThenBranch, AElseBranch);
|
||||
end;
|
||||
|
||||
class function TAst.LambdaExpr(const AParameters: array of IIdentifierNode; const ABody: IExpressionNode): ILambdaExpressionNode;
|
||||
class function TAst.LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode): ILambdaExpressionNode;
|
||||
begin
|
||||
Result := TLambdaExpressionNode.Create(AParameters, ABody);
|
||||
end;
|
||||
@@ -757,6 +804,23 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TExecutionScope.AssignValue(const Name: string; const Value: TAstValue);
|
||||
begin
|
||||
if FVariables.ContainsKey(Name) then
|
||||
FVariables.AddOrSetValue(Name, Value)
|
||||
else if Assigned(FParent) then
|
||||
FParent.AssignValue(Name, Value)
|
||||
else
|
||||
raise Exception.CreateFmt('Cannot assign to undeclared variable "%s".', [Name]);
|
||||
end;
|
||||
|
||||
procedure TExecutionScope.Clear;
|
||||
begin
|
||||
FVariables.Clear;
|
||||
if Assigned(FParent) then
|
||||
FParent.Clear;
|
||||
end;
|
||||
|
||||
procedure TExecutionScope.DumpScope(const ABuilder: TStringBuilder; AIndent: Integer);
|
||||
var
|
||||
pair: TPair<string, TAstValue>;
|
||||
|
||||
Reference in New Issue
Block a user