Scope Index optimized

This commit is contained in:
Michael Schimmel
2025-09-15 10:39:39 +02:00
parent d731048b41
commit c913f9dbc5
4 changed files with 35 additions and 69 deletions
+1 -59
View File
@@ -21,18 +21,11 @@ type
private
FScope: IExecutionScope;
protected
function IsTruthy(const AValue: TDataValue): Boolean;
function IsTruthy(const AValue: TDataValue): Boolean; inline;
// Returns a closure that can create the correct type of visitor for a lambda's body.
function CreateVisitorFactory: TVisitorFactory; virtual;
// Creates the callable closure for a lambda expression. No longer virtual.
function CreateLambdaClosure(
const Node: ILambdaExpressionNode;
const ACapturedCells: TArray<IValueCell>;
const AClosureScope: IExecutionScope
): TDataValue;
property Scope: IExecutionScope read FScope;
public
constructor Create(const AScope: IExecutionScope);
@@ -128,57 +121,6 @@ begin
end;
end;
function TEvaluatorVisitor.CreateLambdaClosure(
const Node: ILambdaExpressionNode;
const ACapturedCells: TArray<IValueCell>;
const AClosureScope: IExecutionScope
): TDataValue;
var
closureValue: TDataValue;
visitorFactory: TVisitorFactory;
begin
// Get the appropriate factory via virtual dispatch.
visitorFactory := CreateVisitorFactory();
closureValue :=
TDataValue.TFunc(
function(const ArgValues: TArray<TDataValue>): TDataValue
var
lambdaScope: IExecutionScope;
bodyVisitor: IAstVisitor;
i: Integer;
adr: TResolvedAddress;
begin
if (Length(ArgValues) <> Length(Node.Parameters)) then
raise EArgumentException
.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(Node.Parameters), Length(ArgValues)]);
lambdaScope := TExecutionScope.Create(AClosureScope, Node.ScopeDescriptor, ACapturedCells);
adr.Kind := akLocalOrParent;
adr.ScopeDepth := 0;
// Set 'Self' (slot 0) to the captured closureValue for recursion.
adr.SlotIndex := 0;
lambdaScope.Cell[adr].Value := closureValue;
// Populate the actual parameters.
for i := 0 to High(ArgValues) do
begin
adr.SlotIndex := Node.Parameters[i].Address.SlotIndex;
lambdaScope.Cell[adr].Value := ArgValues[i];
end;
// Use the injected factory to create the visitor for the lambda's body.
bodyVisitor := visitorFactory(lambdaScope);
Result := Node.Body.Accept(bodyVisitor);
end
);
Result := closureValue;
end;
function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
var
capturedCells: TArray<IValueCell>;