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