Binding
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user