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; function GetClosureScope: TExecutionScope; {$endregion} property Body: IExpressionNode read GetBody; property Parameters: TList read GetParameters; property ClosureScope: TExecutionScope read GetClosureScope; end; // Factory function to create a new closure value. function CreateDataClosureValue( AMethodType: IDataMethodType; ABody: IExpressionNode; AParameters: TList; 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; FClosureScope: TExecutionScope; // IDataValue function GetDataType: IDataType; function GetAsString: string; // IDataMethodValue function GetValue: TDataMethodProc; // IDataClosureValue function GetBody: IExpressionNode; function GetParameters: TList; function GetClosureScope: TExecutionScope; public constructor Create( AMethodType: IDataMethodType; ABody: IExpressionNode; AParameters: TList; ACClosureScope: TExecutionScope ); end; function CreateDataClosureValue( AMethodType: IDataMethodType; ABody: IExpressionNode; AParameters: TList; AClosureScope: TExecutionScope ): IDataClosureValue; begin Result := TDataClosureValueImpl.Create(AMethodType, ABody, AParameters, AClosureScope); end; { TDataClosureValueImpl } constructor TDataClosureValueImpl.Create( AMethodType: IDataMethodType; ABody: IExpressionNode; AParameters: TList; 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 := ''; 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; 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.