Files
MycLib/Src/AST/Myc.Ast.Closure.pas
T
Michael Schimmel 9419f5cd03 AST refactoring
2025-08-28 15:14:08 +02:00

125 lines
3.5 KiB
ObjectPascal

unit Myc.Ast.Closure;
interface
uses
System.Classes,
System.Generics.Collections,
Myc.Data.Types,
Myc.Ast,
Myc.Ast.Scope;
type
// A closure is a specific kind of method value that is defined by the evaluator.
// It holds the AST body and its captured scope.
IDataClosureValue = interface(IDataMethodValue)
['{2704586B-E4BD-47AA-B05D-FD441AE6D818}']
{$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;
// Factory function to create a new closure value.
function CreateDataClosureValue(
AMethodType: IDataMethodType;
ABody: IExpressionNode;
AParameters: TList<IIdentifierNode>;
AClosureScope: TExecutionScope
): IDataClosureValue;
implementation
uses
System.SysUtils;
type
{ TDataClosureValueImpl }
// Concrete implementation of the IDataClosureValue interface.
TDataClosureValueImpl = class(TInterfacedObject, IDataValue, IDataClosureValue)
private
FMethodType: IDataMethodType;
FBody: IExpressionNode;
FParameters: TList<IIdentifierNode>;
FClosureScope: TExecutionScope;
// IDataValue
function GetDataType: IDataType;
function GetAsString: string;
// IDataMethodValue
function GetValue: TDataMethodProc;
// IDataClosureValue
function GetBody: IExpressionNode;
function GetParameters: TList<IIdentifierNode>;
function GetClosureScope: TExecutionScope;
public
constructor Create(
AMethodType: IDataMethodType;
ABody: IExpressionNode;
AParameters: TList<IIdentifierNode>;
ACClosureScope: TExecutionScope
);
end;
function CreateDataClosureValue(
AMethodType: IDataMethodType;
ABody: IExpressionNode;
AParameters: TList<IIdentifierNode>;
AClosureScope: TExecutionScope
): IDataClosureValue;
begin
Result := TDataClosureValueImpl.Create(AMethodType, ABody, AParameters, AClosureScope);
end;
{ TDataClosureValueImpl }
constructor TDataClosureValueImpl.Create(
AMethodType: IDataMethodType;
ABody: IExpressionNode;
AParameters: TList<IIdentifierNode>;
ACClosureScope: TExecutionScope
);
begin
inherited Create;
FMethodType := AMethodType;
FBody := ABody;
FParameters := AParameters; // Note: We are taking ownership of the list reference
FClosureScope := ACClosureScope;
end;
function TDataClosureValueImpl.GetAsString: string;
begin
Result := '<CLOSURE>';
end;
function TDataClosureValueImpl.GetBody: IExpressionNode;
begin
Result := FBody;
end;
function TDataClosureValueImpl.GetClosureScope: TExecutionScope;
begin
Result := FClosureScope;
end;
function TDataClosureValueImpl.GetDataType: IDataType;
begin
Result := FMethodType;
end;
function TDataClosureValueImpl.GetParameters: TList<IIdentifierNode>;
begin
Result := FParameters;
end;
function TDataClosureValueImpl.GetValue: TDataMethodProc;
begin
// This direct execution path is no longer used for closures.
raise ENotSupportedException.Create('Cannot get raw method proc from a closure object.');
end;
end.