Generic Visitors
This commit is contained in:
@@ -24,26 +24,18 @@ type
|
||||
function Visit(const Node: IAstNode): TDataValue; virtual;
|
||||
function CreateVisitorFactory: TEvaluatorFactory; virtual;
|
||||
|
||||
// Nur noch die für die Ausführung relevanten Methoden
|
||||
function VisitConstant(const N: IConstantNode): TDataValue; virtual;
|
||||
function VisitIdentifier(const N: IIdentifierNode): TDataValue; virtual;
|
||||
function VisitKeyword(const N: IKeywordNode): TDataValue; virtual;
|
||||
function VisitParameterList(const N: IParameterList): TDataValue; virtual;
|
||||
function VisitArgumentList(const N: IArgumentList): TDataValue; virtual;
|
||||
function VisitExpressionList(const N: IExpressionList): TDataValue; virtual;
|
||||
function VisitRecordFieldList(const N: IRecordFieldList): TDataValue; virtual;
|
||||
function VisitRecordField(const N: IRecordFieldNode): TDataValue; virtual;
|
||||
function VisitIfExpression(const N: IIfExpressionNode): TDataValue; virtual;
|
||||
function VisitCondExpression(const N: ICondExpressionNode): TDataValue; virtual;
|
||||
function VisitLambdaExpression(const N: ILambdaExpressionNode): TDataValue; virtual;
|
||||
function VisitFunctionCall(const N: IFunctionCallNode): TDataValue; virtual;
|
||||
function VisitMacroExpansionNode(const N: IMacroExpansionNode): TDataValue; virtual;
|
||||
function VisitBlockExpression(const N: IBlockExpressionNode): TDataValue; virtual;
|
||||
function VisitExpressionList(const N: IExpressionList): TDataValue; virtual;
|
||||
function VisitVariableDeclaration(const N: IVariableDeclarationNode): TDataValue; virtual;
|
||||
function VisitAssignment(const N: IAssignmentNode): TDataValue; virtual;
|
||||
function VisitMacroDefinition(const N: IMacroDefinitionNode): TDataValue; virtual;
|
||||
function VisitQuasiquote(const N: IQuasiquoteNode): TDataValue; virtual;
|
||||
function VisitUnquote(const N: IUnquoteNode): TDataValue; virtual;
|
||||
function VisitUnquoteSplicing(const N: IUnquoteSplicingNode): TDataValue; virtual;
|
||||
function VisitIndexer(const N: IIndexerNode): TDataValue; virtual;
|
||||
function VisitMemberAccess(const N: IMemberAccessNode): TDataValue; virtual;
|
||||
function VisitRecordLiteral(const N: IRecordLiteralNode): TDataValue; virtual;
|
||||
@@ -51,10 +43,6 @@ type
|
||||
function VisitAddSeriesItem(const N: IAddSeriesItemNode): TDataValue; virtual;
|
||||
function VisitSeriesLength(const N: ISeriesLengthNode): TDataValue; virtual;
|
||||
function VisitRecurNode(const N: IRecurNode): TDataValue; virtual;
|
||||
function VisitNop(const N: INopNode): TDataValue; virtual;
|
||||
function VisitPipeInput(const N: IPipeInputNode): TDataValue; virtual;
|
||||
function VisitPipeSelectorList(const N: IPipeSelectorList): TDataValue; virtual;
|
||||
function VisitPipeInputList(const N: IPipeInputList): TDataValue; virtual;
|
||||
function VisitPipe(const N: IPipeNode): TDataValue; virtual;
|
||||
|
||||
function IsTruthy(const AValue: TDataValue): Boolean; inline;
|
||||
@@ -100,6 +88,7 @@ end;
|
||||
|
||||
function TEvaluatorVisitor.Visit(const Node: IAstNode): TDataValue;
|
||||
begin
|
||||
// Der Hot-Path: Direkter Dispatch ohne Umweg über ungenutzte Methoden.
|
||||
case Node.Kind of
|
||||
akConstant: Result := VisitConstant(Node.AsConstant);
|
||||
akIdentifier: Result := VisitIdentifier(Node.AsIdentifier);
|
||||
@@ -108,8 +97,8 @@ begin
|
||||
akCondExpression: Result := VisitCondExpression(Node.AsCondExpression);
|
||||
akLambdaExpression: Result := VisitLambdaExpression(Node.AsLambdaExpression);
|
||||
akFunctionCall: Result := VisitFunctionCall(Node.AsFunctionCall);
|
||||
akMacroExpansion: Result := VisitMacroExpansionNode(Node.AsMacroExpansion);
|
||||
akBlockExpression: Result := VisitBlockExpression(Node.AsBlockExpression);
|
||||
akExpressionList: Result := VisitExpressionList(Node.AsExpressionList);
|
||||
akVariableDeclaration: Result := VisitVariableDeclaration(Node.AsVariableDeclaration);
|
||||
akAssignment: Result := VisitAssignment(Node.AsAssignment);
|
||||
akIndexer: Result := VisitIndexer(Node.AsIndexer);
|
||||
@@ -119,9 +108,9 @@ begin
|
||||
akAddSeriesItem: Result := VisitAddSeriesItem(Node.AsAddSeriesItem);
|
||||
akSeriesLength: Result := VisitSeriesLength(Node.AsSeriesLength);
|
||||
akRecur: Result := VisitRecurNode(Node.AsRecur);
|
||||
akNop: Result := VisitNop(Node.AsNop);
|
||||
akPipe: Result := VisitPipe(Node.AsPipe);
|
||||
akExpressionList: Result := VisitExpressionList(Node.AsExpressionList);
|
||||
akMacroExpansion: Result := Visit(Node.AsMacroExpansion.ExpandedBody);
|
||||
akNop: Result := TDataValue.Void;
|
||||
else
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
@@ -129,7 +118,7 @@ end;
|
||||
|
||||
class procedure TEvaluatorVisitor.HandleTCO(var ResultValue: TDataValue);
|
||||
begin
|
||||
while ResultValue.Kind = vkGeneric do
|
||||
while (ResultValue.Kind = vkGeneric) do
|
||||
begin
|
||||
var thunk := ResultValue.AsGeneric<TThunk>;
|
||||
var callee := thunk.Callee.AsMethod();
|
||||
@@ -169,8 +158,6 @@ begin
|
||||
Result := function(const AScope: IExecutionScope): IEvaluatorVisitor begin Result := TEvaluatorVisitor.Create(AScope); end;
|
||||
end;
|
||||
|
||||
// --- Implementations ---
|
||||
|
||||
function TEvaluatorVisitor.VisitConstant(const N: IConstantNode): TDataValue;
|
||||
begin
|
||||
Result := N.Value;
|
||||
@@ -222,7 +209,7 @@ begin
|
||||
raise EEvaluatorException.Create('Arg mismatch');
|
||||
lambdaScope := TScope.CreateScope(closureScope, descriptor, capturedCells);
|
||||
|
||||
// Self-reference for recursion
|
||||
// Self-reference for recursion (Slot 0)
|
||||
lambdaScope.SetValues(TResolvedAddress.Create(akLocalOrParent, 0, 0), TDataValue(closure));
|
||||
|
||||
for k := 0 to params.Count - 1 do
|
||||
@@ -248,13 +235,14 @@ begin
|
||||
|
||||
Result := N.StaticTarget(argValues);
|
||||
if not N.IsTailCall then
|
||||
HandleTCO(Result); // Flushes stack if not tail
|
||||
HandleTCO(Result);
|
||||
end
|
||||
else
|
||||
begin
|
||||
calleeValue := Visit(N.Callee);
|
||||
if calleeValue.Kind <> vkMethod then
|
||||
if (calleeValue.Kind <> vkMethod) then
|
||||
raise EEvaluatorException.Create('Not a function');
|
||||
|
||||
SetLength(argValues, N.Arguments.Count);
|
||||
for i := 0 to N.Arguments.Count - 1 do
|
||||
argValues[i] := Visit(N.Arguments[i]);
|
||||
@@ -320,17 +308,12 @@ function TEvaluatorVisitor.VisitVariableDeclaration(const N: IVariableDeclaratio
|
||||
var
|
||||
ident: IIdentifierNode;
|
||||
begin
|
||||
// 1. Initialisator auswerten
|
||||
if Assigned(N.Initializer) then
|
||||
Result := Visit(N.Initializer)
|
||||
else
|
||||
Result := TDataValue.Void;
|
||||
|
||||
// 2. Das Target-Identifier-Interface extrahieren
|
||||
// N.Target ist IAstNode, wir brauchen IIdentifierNode für die Adresse
|
||||
ident := N.Target.AsIdentifier;
|
||||
|
||||
// 3. Im Scope speichern
|
||||
if N.IsBoxed then
|
||||
FScope.DefineBoxed(ident.Address.SlotIndex, Result)
|
||||
else
|
||||
@@ -351,9 +334,9 @@ begin
|
||||
if base.IsVoid then
|
||||
exit(TDataValue.Void);
|
||||
idx := Visit(N.Index);
|
||||
if base.Kind = vkSeries then
|
||||
if (base.Kind = vkSeries) then
|
||||
Result := TDataValue(base.AsSeries.Items[Integer(idx.AsScalar.Value.AsInt64)])
|
||||
else if base.Kind = vkRecordSeries then
|
||||
else if (base.Kind = vkRecordSeries) then
|
||||
begin
|
||||
var rs := base.AsRecordSeries;
|
||||
var vals: TArray<TScalar.TValue>;
|
||||
@@ -416,7 +399,7 @@ end;
|
||||
|
||||
function TEvaluatorVisitor.VisitAddSeriesItem(const N: IAddSeriesItemNode): TDataValue;
|
||||
begin
|
||||
var lb := -1;
|
||||
var lb: Int64 := -1;
|
||||
if Assigned(N.Lookback) then
|
||||
lb := Visit(N.Lookback).AsScalar.Value.AsInt64;
|
||||
FScope[N.Series.Address].AsRecordSeries.Add(Visit(N.Value).AsScalarRecord, lb);
|
||||
@@ -448,7 +431,7 @@ begin
|
||||
begin
|
||||
inputNode := N.Inputs[i];
|
||||
inputVal := FScope[inputNode.StreamSource.Address];
|
||||
if inputVal.Kind <> vkStream then
|
||||
if (inputVal.Kind <> vkStream) then
|
||||
raise EEvaluatorException.Create('Stream expected');
|
||||
sources[i] := inputVal.AsStream;
|
||||
sourceSeries := sources[i].Series;
|
||||
@@ -473,7 +456,7 @@ begin
|
||||
begin
|
||||
SetLength(args, Length(S));
|
||||
for k := 0 to High(S) do
|
||||
args[k] := TDataValue(S[k].Items[0]);
|
||||
args[k] := S[k].Items[0];
|
||||
res := lambdaFunc(args);
|
||||
if res.IsVoid then
|
||||
exit(False);
|
||||
@@ -485,57 +468,4 @@ begin
|
||||
Result := TDataValue.FromStream(TPipeStream.Create(config, outputDef, sources, pipeAdapter));
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitMacroDefinition(const N: IMacroDefinitionNode): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitQuasiquote(const N: IQuasiquoteNode): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitUnquote(const N: IUnquoteNode): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitUnquoteSplicing(const N: IUnquoteSplicingNode): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitNop(const N: INopNode): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitParameterList(const N: IParameterList): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitArgumentList(const N: IArgumentList): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitRecordFieldList(const N: IRecordFieldList): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitRecordField(const N: IRecordFieldNode): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitPipeInput(const N: IPipeInputNode): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitPipeSelectorList(const N: IPipeSelectorList): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitPipeInputList(const N: IPipeInputList): TDataValue;
|
||||
begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
function TEvaluatorVisitor.VisitMacroExpansionNode(const N: IMacroExpansionNode): TDataValue;
|
||||
begin
|
||||
Result := Visit(N.ExpandedBody);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@@ -14,8 +14,6 @@ uses
|
||||
type
|
||||
TAstVisitor<T> = class;
|
||||
|
||||
// Handler signature is now strictly based on IAstNode to ensure binary compatibility
|
||||
// with the dispatch array.
|
||||
TNodeHandler<T> = reference to function(const Node: IAstNode): T;
|
||||
|
||||
TAstVisitor<T> = class abstract(TInterfacedObject, IAstVisitor)
|
||||
@@ -32,7 +30,7 @@ type
|
||||
protected
|
||||
// --- Registration ---
|
||||
|
||||
// Register a handler. No generic overload anymore.
|
||||
// Register a handler.
|
||||
procedure Register(Kind: TAstNodeKind; const Handler: TNodeHandler<T>); virtual;
|
||||
|
||||
// Subclasses implement this to call Register()
|
||||
@@ -49,7 +47,7 @@ type
|
||||
end;
|
||||
|
||||
// Helper for transformation visitors (returns IAstNode)
|
||||
// Implements recursive reconstruction: If a child changes, a new node is returned.
|
||||
// Implements recursive reconstruction: If a child changes, a new node is returned, but node.Identity stays the same.
|
||||
TAstTransformer = class abstract(TAstVisitor<IAstNode>)
|
||||
protected
|
||||
// Leaves
|
||||
|
||||
Reference in New Issue
Block a user