125 lines
3.5 KiB
ObjectPascal
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.
|