This commit is contained in:
Michael Schimmel
2025-09-04 21:17:23 +02:00
parent bb74d408da
commit 4a8075fecf
5 changed files with 76 additions and 155 deletions
+15 -23
View File
@@ -88,8 +88,8 @@ type
// The signature for a native Delphi function callable from the script.
TNativeFunction = function(const Args: TArray<TAstValue>): TAstValue;
// Concrete implementation of the IEvaluatorClosure interface for script-defined functions.
TClosureValue = class(TInterfacedObject, IEvaluatorClosure)
// Concrete implementation of the TAstValue.IClosure interface for script-defined functions.
TClosureValue = class(TInterfacedObject, TAstValue.IClosure)
private
FBody: IExpressionNode;
FClosureScope: IExecutionScope;
@@ -97,15 +97,14 @@ type
function GetBody: IExpressionNode;
function GetParameters: TArray<IIdentifierNode>;
function GetClosureScope: IExecutionScope;
function GetLambdaNode: ILambdaExpressionNode;
public
constructor Create(const ALambdaNode: ILambdaExpressionNode; const AClosureScope: IExecutionScope);
property ClosureScope: IExecutionScope read GetClosureScope;
property LambdaNode: ILambdaExpressionNode read GetLambdaNode;
property LambdaNode: ILambdaExpressionNode read FLambdaNode;
end;
// Concrete implementation of IEvaluatorClosure for native Delphi functions.
TNativeClosure = class(TInterfacedObject, IEvaluatorClosure)
// Concrete implementation of TAstValue.IClosure for native Delphi functions.
TNativeClosure = class(TInterfacedObject, TAstValue.IClosure)
private
FMethod: TNativeFunction;
function GetBody: IExpressionNode;
@@ -196,7 +195,7 @@ end;
procedure RegisterNativeFunctions(const AScope: IExecutionScope);
var
closure: IEvaluatorClosure;
closure: TAstValue.IClosure;
begin
// Use 'Define' to clearly state that we are adding a new variable
// to the global scope before the binder runs.
@@ -224,11 +223,6 @@ begin
Result := FClosureScope;
end;
function TClosureValue.GetLambdaNode: ILambdaExpressionNode;
begin
Result := FLambdaNode;
end;
function TClosureValue.GetParameters: TArray<IIdentifierNode>;
begin
Result := FLambdaNode.Parameters;
@@ -294,7 +288,7 @@ var
lookback: Int64;
begin
// The target series must have been resolved by the binder.
seriesVar := FScope[Node.Series.Resolve];
seriesVar := FScope[Node.Series.Address];
itemValue := Node.Value.Accept(Self);
lookback := -1;
@@ -345,7 +339,7 @@ end;
function TEvaluatorVisitor.VisitAssignment(const Node: IAssignmentNode): TAstValue;
begin
Result := Node.Value.Accept(Self);
FScope[Node.Identifier.Resolve] := Result;
FScope[Node.Identifier.Address] := Result;
end;
function TEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TAstValue;
@@ -378,7 +372,7 @@ end;
function TEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TAstValue;
begin
Result := FScope[Node.Resolve];
Result := FScope[Node.Address];
end;
function TEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TAstValue;
@@ -475,7 +469,7 @@ begin
else
value := TAstValue.Void;
FScope[Node.Identifier.Resolve] := value;
FScope[Node.Identifier.Address] := value;
Result := value;
end;
@@ -488,10 +482,8 @@ end;
function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue;
var
calleeValue: TAstValue;
closure: IEvaluatorClosure;
closure: TAstValue.IClosure;
i: Integer;
callScope: IExecutionScope;
descriptor: IScopeDescriptor;
begin
calleeValue := Node.Callee.Accept(Self);
@@ -514,20 +506,20 @@ begin
raise EArgumentException
.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(closure.Parameters), Node.Arguments.Count]);
descriptor := (closure as TClosureValue).LambdaNode.ScopeDescriptor;
var descriptor := (closure as TClosureValue).LambdaNode.ScopeDescriptor;
if not Assigned(descriptor) then
raise EParserError.Create('Lambda has no scope descriptor. Did the binder run?');
var callScope := descriptor.CreateScope(closure.ClosureScope);
var adr: TResolvedAddress;
adr.ScopeDepth := 0;
adr.SlotIndex := 0;
callScope := descriptor.Instantiate(closure.ClosureScope);
callScope[adr] := calleeValue;
for i := 0 to Node.Arguments.Count - 1 do
begin
adr.SlotIndex := closure.Parameters[i].Resolve.SlotIndex;
adr.SlotIndex := closure.Parameters[i].Address.SlotIndex;
callScope[adr] := Node.Arguments[i].Accept(Self);
end;