Generic Visitor Pattern
This commit is contained in:
@@ -10,56 +10,59 @@ uses
|
|||||||
Myc.Data.Value,
|
Myc.Data.Value,
|
||||||
Myc.Data.Keyword,
|
Myc.Data.Keyword,
|
||||||
Myc.Ast.Nodes,
|
Myc.Ast.Nodes,
|
||||||
Myc.Ast.Scope;
|
Myc.Ast.Scope,
|
||||||
|
Myc.Ast.Visitor;
|
||||||
|
|
||||||
type
|
type
|
||||||
// Exception for runtime errors during script evaluation
|
// Exception for runtime errors during script evaluation
|
||||||
EEvaluatorException = class(EAstException);
|
EEvaluatorException = class(EAstException);
|
||||||
|
|
||||||
// The standard AST evaluator for production use.
|
// The standard AST evaluator for production use.
|
||||||
TEvaluatorVisitor = class(TInterfacedObject, IAstVisitor, IEvaluatorVisitor)
|
TEvaluatorVisitor = class(TAstVisitor<TDataValue>, IEvaluatorVisitor)
|
||||||
private
|
private
|
||||||
FScope: IExecutionScope;
|
FScope: IExecutionScope;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
// IAstVisitor methods made virtual for TDebugEvaluatorVisitor to override
|
// Setup the registry-based handlers
|
||||||
function VisitConstant(const Node: IConstantNode): TDataValue; virtual;
|
procedure SetupHandlers; override;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; virtual;
|
|
||||||
function VisitKeyword(const Node: IKeywordNode): TDataValue; virtual;
|
|
||||||
|
|
||||||
// List Visitors
|
// --- Core Logic Implementation (Legacy Virtual Overrides) ---
|
||||||
function VisitParameterList(const Node: IParameterList): TDataValue; virtual;
|
// These are kept as virtual methods so TDebugEvaluatorVisitor can still override them.
|
||||||
function VisitArgumentList(const Node: IArgumentList): TDataValue; virtual;
|
function VisitConstant(const Node: IConstantNode): TDataValue; override;
|
||||||
function VisitExpressionList(const Node: IExpressionList): TDataValue; virtual;
|
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
|
||||||
function VisitRecordFieldList(const Node: IRecordFieldList): TDataValue; virtual;
|
function VisitKeyword(const Node: IKeywordNode): TDataValue; override;
|
||||||
function VisitRecordField(const Node: IRecordFieldNode): TDataValue; virtual;
|
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual;
|
function VisitParameterList(const Node: IParameterList): TDataValue; override;
|
||||||
function VisitCondExpression(const Node: ICondExpressionNode): TDataValue; virtual;
|
function VisitArgumentList(const Node: IArgumentList): TDataValue; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual;
|
function VisitExpressionList(const Node: IExpressionList): TDataValue; override;
|
||||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; virtual;
|
function VisitRecordFieldList(const Node: IRecordFieldList): TDataValue; override;
|
||||||
function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; virtual;
|
function VisitRecordField(const Node: IRecordFieldNode): TDataValue; override;
|
||||||
function VisitUnquote(const Node: IUnquoteNode): TDataValue; virtual;
|
|
||||||
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; virtual;
|
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; virtual;
|
|
||||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; virtual;
|
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; virtual;
|
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; virtual;
|
|
||||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue; virtual;
|
|
||||||
function VisitIndexer(const Node: IIndexerNode): TDataValue; virtual;
|
|
||||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; virtual;
|
|
||||||
function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; virtual;
|
|
||||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; virtual;
|
|
||||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; virtual;
|
|
||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual;
|
|
||||||
function VisitRecurNode(const Node: IRecurNode): TDataValue; virtual;
|
|
||||||
function VisitNop(const Node: INopNode): TDataValue; virtual;
|
|
||||||
|
|
||||||
// Pipe Support
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
||||||
function VisitPipeInput(const Node: IPipeInputNode): TDataValue; virtual;
|
function VisitCondExpression(const Node: ICondExpressionNode): TDataValue; override;
|
||||||
function VisitPipeSelectorList(const Node: IPipeSelectorList): TDataValue; virtual;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
||||||
function VisitPipeInputList(const Node: IPipeInputList): TDataValue; virtual;
|
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
||||||
function VisitPipe(const Node: IPipeNode): TDataValue; virtual;
|
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; override;
|
||||||
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
||||||
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
||||||
|
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
|
||||||
|
function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; override;
|
||||||
|
function VisitUnquote(const Node: IUnquoteNode): TDataValue; override;
|
||||||
|
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; override;
|
||||||
|
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
|
||||||
|
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
|
||||||
|
function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; override;
|
||||||
|
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
|
||||||
|
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
|
||||||
|
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
|
||||||
|
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
|
||||||
|
function VisitNop(const Node: INopNode): TDataValue; override;
|
||||||
|
|
||||||
|
function VisitPipeInput(const Node: IPipeInputNode): TDataValue; override;
|
||||||
|
function VisitPipeSelectorList(const Node: IPipeSelectorList): TDataValue; override;
|
||||||
|
function VisitPipeInputList(const Node: IPipeInputList): TDataValue; override;
|
||||||
|
function VisitPipe(const Node: IPipeNode): TDataValue; override;
|
||||||
|
|
||||||
function IsTruthy(const AValue: TDataValue): Boolean; inline;
|
function IsTruthy(const AValue: TDataValue): Boolean; inline;
|
||||||
|
|
||||||
@@ -108,9 +111,21 @@ end;
|
|||||||
|
|
||||||
constructor TEvaluatorVisitor.Create(const AScope: IExecutionScope);
|
constructor TEvaluatorVisitor.Create(const AScope: IExecutionScope);
|
||||||
begin
|
begin
|
||||||
|
FScope := AScope;
|
||||||
|
// Base constructor calls SetupHandlers automatically
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Assert(Assigned(AScope));
|
Assert(Assigned(AScope));
|
||||||
FScope := AScope;
|
end;
|
||||||
|
|
||||||
|
procedure TEvaluatorVisitor.SetupHandlers;
|
||||||
|
begin
|
||||||
|
// The base SetupHandlers registers delegates that call the virtual methods (VisitConstant, etc.).
|
||||||
|
// Since TEvaluatorVisitor still implements its logic by overriding these virtual methods (for now),
|
||||||
|
// we just call inherited.
|
||||||
|
//
|
||||||
|
// In Phase 2/3 of refactoring, we would move the logic from VisitConstant directly into
|
||||||
|
// anonymous methods or separate handler functions registered here, bypassing the virtual table.
|
||||||
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.Execute(const RootNode: IAstNode): TDataValue;
|
function TEvaluatorVisitor.Execute(const RootNode: IAstNode): TDataValue;
|
||||||
@@ -119,7 +134,8 @@ begin
|
|||||||
exit(TDataValue.Void);
|
exit(TDataValue.Void);
|
||||||
|
|
||||||
try
|
try
|
||||||
Result := RootNode.Accept(Self);
|
// Call the central dispatch method from TAstVisitor<T>
|
||||||
|
Result := Visit(RootNode);
|
||||||
HandleTCO(Result);
|
HandleTCO(Result);
|
||||||
except
|
except
|
||||||
on E: EAstException do
|
on E: EAstException do
|
||||||
@@ -171,6 +187,23 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// --- Visits Implementation ---
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := Node.Value;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := TDataValue(TScalar.FromKeyword(Node.Value));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := FScope[Node.Address];
|
||||||
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
var
|
var
|
||||||
capturedCells: TArray<IValueCell>;
|
capturedCells: TArray<IValueCell>;
|
||||||
@@ -232,8 +265,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// Create a visitor with the new scope and execute the lambda's body.
|
// Create a visitor with the new scope and execute the lambda's body.
|
||||||
|
// Use the generic Visit method for dispatch
|
||||||
bodyVisitor := visitorFactory(lambdaScope);
|
bodyVisitor := visitorFactory(lambdaScope);
|
||||||
Result := cNode.Body.Accept(bodyVisitor);
|
Result := bodyVisitor.Visit(cNode.Body);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := TDataValue(closure);
|
Result := TDataValue(closure);
|
||||||
@@ -272,7 +306,7 @@ begin
|
|||||||
argList := Node.Arguments;
|
argList := Node.Arguments;
|
||||||
SetLength(argValues, argList.Count);
|
SetLength(argValues, argList.Count);
|
||||||
for i := 0 to argList.Count - 1 do
|
for i := 0 to argList.Count - 1 do
|
||||||
argValues[i] := argList[i].Accept(Self);
|
argValues[i] := Visit(argList[i]); // Use central dispatch
|
||||||
|
|
||||||
// Call static target. Exceptions here are caught by Execute/HandleTCO.
|
// Call static target. Exceptions here are caught by Execute/HandleTCO.
|
||||||
Result := Node.StaticTarget(argValues);
|
Result := Node.StaticTarget(argValues);
|
||||||
@@ -281,14 +315,14 @@ begin
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
// --- Dynamic Path (Default) ---
|
// --- Dynamic Path (Default) ---
|
||||||
calleeValue := Node.Callee.Accept(Self);
|
calleeValue := Visit(Node.Callee);
|
||||||
if calleeValue.Kind <> vkMethod then
|
if calleeValue.Kind <> vkMethod then
|
||||||
raise EEvaluatorException.Create('Expression is not invokable in this context.');
|
raise EEvaluatorException.Create('Expression is not invokable in this context.');
|
||||||
|
|
||||||
argList := Node.Arguments;
|
argList := Node.Arguments;
|
||||||
SetLength(argValues, argList.Count);
|
SetLength(argValues, argList.Count);
|
||||||
for i := 0 to argList.Count - 1 do
|
for i := 0 to argList.Count - 1 do
|
||||||
argValues[i] := argList[i].Accept(Self);
|
argValues[i] := Visit(argList[i]);
|
||||||
|
|
||||||
if Node.IsTailCall then
|
if Node.IsTailCall then
|
||||||
begin
|
begin
|
||||||
@@ -304,7 +338,7 @@ end;
|
|||||||
|
|
||||||
function TEvaluatorVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
function TEvaluatorVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := Node.ExpandedBody.Accept(Self);
|
Result := Visit(Node.ExpandedBody);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitRecurNode(const Node: IRecurNode): TDataValue;
|
function TEvaluatorVisitor.VisitRecurNode(const Node: IRecurNode): TDataValue;
|
||||||
@@ -316,7 +350,7 @@ var
|
|||||||
begin
|
begin
|
||||||
SetLength(argValues, Node.Arguments.Count);
|
SetLength(argValues, Node.Arguments.Count);
|
||||||
for i := 0 to Node.Arguments.Count - 1 do
|
for i := 0 to Node.Arguments.Count - 1 do
|
||||||
argValues[i] := Node.Arguments[i].Accept(Self);
|
argValues[i] := Visit(Node.Arguments[i]);
|
||||||
|
|
||||||
calleeAddress.Kind := akLocalOrParent;
|
calleeAddress.Kind := akLocalOrParent;
|
||||||
calleeAddress.ScopeDepth := 0;
|
calleeAddress.ScopeDepth := 0;
|
||||||
@@ -332,12 +366,12 @@ var
|
|||||||
lookback: Int64;
|
lookback: Int64;
|
||||||
begin
|
begin
|
||||||
seriesVar := FScope[Node.Series.Address];
|
seriesVar := FScope[Node.Series.Address];
|
||||||
itemValue := Node.Value.Accept(Self);
|
itemValue := Visit(Node.Value);
|
||||||
lookback := -1;
|
lookback := -1;
|
||||||
|
|
||||||
if Assigned(Node.Lookback) then
|
if Assigned(Node.Lookback) then
|
||||||
begin
|
begin
|
||||||
lookbackValue := Node.Lookback.Accept(Self);
|
lookbackValue := Visit(Node.Lookback);
|
||||||
if (lookbackValue.Kind <> vkScalar) or (lookbackValue.AsScalar.Kind <> TScalar.TKind.Ordinal) then
|
if (lookbackValue.Kind <> vkScalar) or (lookbackValue.AsScalar.Kind <> TScalar.TKind.Ordinal) then
|
||||||
raise EEvaluatorException.Create('Lookback parameter must be an integer.');
|
raise EEvaluatorException.Create('Lookback parameter must be an integer.');
|
||||||
lookback := lookbackValue.AsScalar.Value.AsInt64;
|
lookback := lookbackValue.AsScalar.Value.AsInt64;
|
||||||
@@ -362,20 +396,10 @@ begin
|
|||||||
if Node.Target.Kind <> akIdentifier then
|
if Node.Target.Kind <> akIdentifier then
|
||||||
raise EEvaluatorException.Create('Runtime Error: Assignment target must be an identifier.');
|
raise EEvaluatorException.Create('Runtime Error: Assignment target must be an identifier.');
|
||||||
|
|
||||||
Result := Node.Value.Accept(Self);
|
Result := Visit(Node.Value);
|
||||||
FScope[Node.Target.AsIdentifier.Address] := Result;
|
FScope[Node.Target.AsIdentifier.Address] := Result;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TDataValue;
|
|
||||||
begin
|
|
||||||
Result := Node.Value;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitKeyword(const Node: IKeywordNode): TDataValue;
|
|
||||||
begin
|
|
||||||
Result := TDataValue(TScalar.FromKeyword(Node.Value));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
function TEvaluatorVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
||||||
var
|
var
|
||||||
def: string;
|
def: string;
|
||||||
@@ -403,11 +427,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
|
||||||
begin
|
|
||||||
Result := FScope[Node.Address];
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
function TEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||||
var
|
var
|
||||||
baseValue, indexValue: TDataValue;
|
baseValue, indexValue: TDataValue;
|
||||||
@@ -420,12 +439,12 @@ var
|
|||||||
memberSeries: ISeries;
|
memberSeries: ISeries;
|
||||||
scalarValue: TScalar;
|
scalarValue: TScalar;
|
||||||
begin
|
begin
|
||||||
baseValue := Node.Base.Accept(Self);
|
baseValue := Visit(Node.Base);
|
||||||
|
|
||||||
if baseValue.IsVoid then
|
if baseValue.IsVoid then
|
||||||
exit(TDataValue.Void);
|
exit(TDataValue.Void);
|
||||||
|
|
||||||
indexValue := Node.Index.Accept(Self);
|
indexValue := Visit(Node.Index);
|
||||||
|
|
||||||
if (indexValue.Kind <> vkScalar) or (indexValue.AsScalar.Kind <> TScalar.TKind.Ordinal) then
|
if (indexValue.Kind <> vkScalar) or (indexValue.AsScalar.Kind <> TScalar.TKind.Ordinal) then
|
||||||
raise EEvaluatorException.Create('Indexer `[]` requires an integer argument.');
|
raise EEvaluatorException.Create('Indexer `[]` requires an integer argument.');
|
||||||
@@ -471,7 +490,7 @@ function TEvaluatorVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDa
|
|||||||
var
|
var
|
||||||
baseValue: TDataValue;
|
baseValue: TDataValue;
|
||||||
begin
|
begin
|
||||||
baseValue := Node.Base.Accept(Self);
|
baseValue := Visit(Node.Base);
|
||||||
|
|
||||||
if baseValue.IsVoid then
|
if baseValue.IsVoid then
|
||||||
exit(TDataValue.Void);
|
exit(TDataValue.Void);
|
||||||
@@ -498,7 +517,7 @@ begin
|
|||||||
for i := 0 to Node.Fields.Count - 1 do
|
for i := 0 to Node.Fields.Count - 1 do
|
||||||
begin
|
begin
|
||||||
var field := Node.Fields[i];
|
var field := Node.Fields[i];
|
||||||
genFields[i] := TPair<IKeyword, TDataValue>.Create(field.Key.Value, field.Value.Accept(Self));
|
genFields[i] := TPair<IKeyword, TDataValue>.Create(field.Key.Value, Visit(field.Value));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := TDataValue.FromGenericRecord(TKeywordMapping<TDataValue>.Create(genFields));
|
Result := TDataValue.FromGenericRecord(TKeywordMapping<TDataValue>.Create(genFields));
|
||||||
@@ -511,7 +530,7 @@ begin
|
|||||||
for i := 0 to Node.Fields.Count - 1 do
|
for i := 0 to Node.Fields.Count - 1 do
|
||||||
begin
|
begin
|
||||||
var field := Node.Fields[i];
|
var field := Node.Fields[i];
|
||||||
var valData := field.Value.Accept(Self);
|
var valData := Visit(field.Value);
|
||||||
values[i] := valData.AsScalar.Value;
|
values[i] := valData.AsScalar.Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -529,7 +548,7 @@ begin
|
|||||||
raise EEvaluatorException.Create('Runtime Error: Variable declaration target must be an identifier.');
|
raise EEvaluatorException.Create('Runtime Error: Variable declaration target must be an identifier.');
|
||||||
|
|
||||||
if Assigned(Node.Initializer) then
|
if Assigned(Node.Initializer) then
|
||||||
Result := Node.Initializer.Accept(Self)
|
Result := Visit(Node.Initializer)
|
||||||
else
|
else
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
|
|
||||||
@@ -548,10 +567,10 @@ end;
|
|||||||
|
|
||||||
function TEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
if IsTruthy(Node.Condition.Accept(Self)) then
|
if IsTruthy(Visit(Node.Condition)) then
|
||||||
Result := Node.ThenBranch.Accept(Self)
|
Result := Visit(Node.ThenBranch)
|
||||||
else if Assigned(Node.ElseBranch) then
|
else if Assigned(Node.ElseBranch) then
|
||||||
Result := Node.ElseBranch.Accept(Self)
|
Result := Visit(Node.ElseBranch)
|
||||||
else
|
else
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
@@ -562,20 +581,20 @@ var
|
|||||||
begin
|
begin
|
||||||
for pair in Node.Pairs do
|
for pair in Node.Pairs do
|
||||||
begin
|
begin
|
||||||
if IsTruthy(pair.Condition.Accept(Self)) then
|
if IsTruthy(Visit(pair.Condition)) then
|
||||||
begin
|
begin
|
||||||
Result := pair.Branch.Accept(Self);
|
Result := Visit(pair.Branch);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
// Else branch is mandatory in AST (though can be Nop/Void in source if omitted and normalized)
|
// Else branch is mandatory in AST (though can be Nop/Void in source if omitted and normalized)
|
||||||
Result := Node.ElseBranch.Accept(Self);
|
Result := Visit(Node.ElseBranch);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
// Delegate to ExpressionList visitor
|
// Delegate to ExpressionList visitor via central Visit dispatch (default handler maps to VisitExpressionList)
|
||||||
Result := Node.Expressions.Accept(Self);
|
Result := Visit(Node.Expressions);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitExpressionList(const Node: IExpressionList): TDataValue;
|
function TEvaluatorVisitor.VisitExpressionList(const Node: IExpressionList): TDataValue;
|
||||||
@@ -584,7 +603,7 @@ var
|
|||||||
begin
|
begin
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
for i := 0 to Node.Count - 1 do
|
for i := 0 to Node.Count - 1 do
|
||||||
Result := Node[i].Accept(Self);
|
Result := Visit(Node[i]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitNop(const Node: INopNode): TDataValue;
|
function TEvaluatorVisitor.VisitNop(const Node: INopNode): TDataValue;
|
||||||
@@ -610,7 +629,7 @@ begin
|
|||||||
Result := TDataValue(TScalar.FromInt64(len));
|
Result := TDataValue(TScalar.FromInt64(len));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- List Visitor Stubs (Mostly Unused directly, but required by Interface) ---
|
// --- List Visitor Stubs (Default to Void if not implemented specifically) ---
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitParameterList(const Node: IParameterList): TDataValue;
|
function TEvaluatorVisitor.VisitParameterList(const Node: IParameterList): TDataValue;
|
||||||
begin
|
begin
|
||||||
@@ -619,20 +638,16 @@ end;
|
|||||||
|
|
||||||
function TEvaluatorVisitor.VisitArgumentList(const Node: IArgumentList): TDataValue;
|
function TEvaluatorVisitor.VisitArgumentList(const Node: IArgumentList): TDataValue;
|
||||||
begin
|
begin
|
||||||
// Could evaluate arguments here and return an array-wrapped TDataValue,
|
|
||||||
// but VisitFunctionCall handles iteration manually for efficiency.
|
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
function TEvaluatorVisitor.VisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
||||||
begin
|
begin
|
||||||
// Handled by VisitRecordLiteral
|
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
function TEvaluatorVisitor.VisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
// Handled by manual iteration in VisitRecordLiteral
|
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -711,7 +726,7 @@ begin
|
|||||||
outputDef := Node.StaticType.Definition;
|
outputDef := Node.StaticType.Definition;
|
||||||
|
|
||||||
// 3. Compile Lambda
|
// 3. Compile Lambda
|
||||||
lambdaFunc := Node.Transformation.Accept(Self).AsMethod();
|
lambdaFunc := Visit(Node.Transformation).AsMethod();
|
||||||
|
|
||||||
// 4. Create Adapter
|
// 4. Create Adapter
|
||||||
pipeAdapter :=
|
pipeAdapter :=
|
||||||
|
|||||||
@@ -64,6 +64,12 @@ type
|
|||||||
property Errors: TArray<TCompilerError> read FErrors;
|
property Errors: TArray<TCompilerError> read FErrors;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Exception for the new visitor registry dispatch
|
||||||
|
ENoHandlerException = class(EAstException)
|
||||||
|
public
|
||||||
|
constructor Create(const KindName: string);
|
||||||
|
end;
|
||||||
|
|
||||||
TCompiledFunction = record
|
TCompiledFunction = record
|
||||||
public
|
public
|
||||||
Func: TDataValue.TFunc;
|
Func: TDataValue.TFunc;
|
||||||
@@ -507,6 +513,10 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
IAstVisitor = interface
|
IAstVisitor = interface
|
||||||
|
// --- Central Dispatch Method (New) ---
|
||||||
|
function Visit(const Node: IAstNode): TDataValue;
|
||||||
|
|
||||||
|
// --- Specific Methods (Legacy / Hybrid Support) ---
|
||||||
function VisitConstant(const Node: IConstantNode): TDataValue;
|
function VisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
function VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||||
function VisitKeyword(const Node: IKeywordNode): TDataValue;
|
function VisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||||
@@ -1268,6 +1278,13 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ ENoHandlerException }
|
||||||
|
|
||||||
|
constructor ENoHandlerException.Create(const KindName: string);
|
||||||
|
begin
|
||||||
|
inherited CreateFmt('No visitor handler registered for AST node kind: %s', [KindName]);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TAstNode }
|
{ TAstNode }
|
||||||
|
|
||||||
constructor TAstNode.Create(const AIdentity: IAstIdentity);
|
constructor TAstNode.Create(const AIdentity: IAstIdentity);
|
||||||
|
|||||||
+206
-103
@@ -12,9 +12,20 @@ uses
|
|||||||
Myc.Ast.Identities;
|
Myc.Ast.Identities;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TAstVisitor<T> = class;
|
||||||
|
|
||||||
|
// Delegate for handling a specific node kind within the visitor context
|
||||||
|
TNodeHandler<T> = reference to function(const Node: IAstNode): T;
|
||||||
|
|
||||||
TAstVisitor<T> = class abstract(TInterfacedObject, IAstVisitor)
|
TAstVisitor<T> = class abstract(TInterfacedObject, IAstVisitor)
|
||||||
strict private
|
strict private
|
||||||
|
// The registry for O(1) dispatch based on TAstNodeKind
|
||||||
|
FHandlers: array[TAstNodeKind] of TNodeHandler<T>;
|
||||||
|
|
||||||
// IAstVisitor explicit implementation (bridge methods)
|
// IAstVisitor explicit implementation (bridge methods)
|
||||||
|
function IAstVisitor.Visit = VisitBridge;
|
||||||
|
|
||||||
|
// Legacy bridge methods for IAstVisitor interface compliance
|
||||||
function IAstVisitor.VisitConstant = DoVisitConstant;
|
function IAstVisitor.VisitConstant = DoVisitConstant;
|
||||||
function IAstVisitor.VisitIdentifier = DoVisitIdentifier;
|
function IAstVisitor.VisitIdentifier = DoVisitIdentifier;
|
||||||
function IAstVisitor.VisitKeyword = DoVisitKeyword;
|
function IAstVisitor.VisitKeyword = DoVisitKeyword;
|
||||||
@@ -46,23 +57,21 @@ type
|
|||||||
function IAstVisitor.VisitRecurNode = DoVisitRecurNode;
|
function IAstVisitor.VisitRecurNode = DoVisitRecurNode;
|
||||||
function IAstVisitor.VisitNop = DoVisitNop;
|
function IAstVisitor.VisitNop = DoVisitNop;
|
||||||
|
|
||||||
// Pipe Support
|
|
||||||
function IAstVisitor.VisitPipeInput = DoVisitPipeInput;
|
function IAstVisitor.VisitPipeInput = DoVisitPipeInput;
|
||||||
function IAstVisitor.VisitPipeSelectorList = DoVisitPipeSelectorList;
|
function IAstVisitor.VisitPipeSelectorList = DoVisitPipeSelectorList;
|
||||||
function IAstVisitor.VisitPipeInputList = DoVisitPipeInputList;
|
function IAstVisitor.VisitPipeInputList = DoVisitPipeInputList;
|
||||||
function IAstVisitor.VisitPipe = DoVisitPipe;
|
function IAstVisitor.VisitPipe = DoVisitPipe;
|
||||||
|
|
||||||
// Private bridge method implementations
|
// Private helpers to wrap T into TDataValue for the non-generic interface
|
||||||
|
function VisitBridge(const Node: IAstNode): TDataValue;
|
||||||
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
function DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
function DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||||
function DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
function DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||||
|
|
||||||
function DoVisitParameterList(const Node: IParameterList): TDataValue;
|
function DoVisitParameterList(const Node: IParameterList): TDataValue;
|
||||||
function DoVisitArgumentList(const Node: IArgumentList): TDataValue;
|
function DoVisitArgumentList(const Node: IArgumentList): TDataValue;
|
||||||
function DoVisitExpressionList(const Node: IExpressionList): TDataValue;
|
function DoVisitExpressionList(const Node: IExpressionList): TDataValue;
|
||||||
function DoVisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
function DoVisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
||||||
function DoVisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
function DoVisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
|
|
||||||
function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
function DoVisitCondExpression(const Node: ICondExpressionNode): TDataValue;
|
function DoVisitCondExpression(const Node: ICondExpressionNode): TDataValue;
|
||||||
function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
@@ -83,17 +92,26 @@ type
|
|||||||
function DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
function DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||||
function DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
function DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
||||||
function DoVisitNop(const Node: INopNode): TDataValue;
|
function DoVisitNop(const Node: INopNode): TDataValue;
|
||||||
|
|
||||||
function DoVisitPipeInput(const Node: IPipeInputNode): TDataValue;
|
function DoVisitPipeInput(const Node: IPipeInputNode): TDataValue;
|
||||||
function DoVisitPipeSelectorList(const Node: IPipeSelectorList): TDataValue;
|
function DoVisitPipeSelectorList(const Node: IPipeSelectorList): TDataValue;
|
||||||
function DoVisitPipeInputList(const Node: IPipeInputList): TDataValue;
|
function DoVisitPipeInputList(const Node: IPipeInputList): TDataValue;
|
||||||
function DoVisitPipe(const Node: IPipeNode): TDataValue;
|
function DoVisitPipe(const Node: IPipeNode): TDataValue;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
// Visit a node.
|
// Registers a handler for a specific node kind.
|
||||||
function Accept(const Node: IAstNode): T; virtual;
|
// Subclasses can call this in their constructor/SetupHandlers to override behavior without implementing VisitXYZ.
|
||||||
|
procedure RegisterHandler(Kind: TAstNodeKind; Handler: TNodeHandler<T>);
|
||||||
|
|
||||||
// Default visitor functions implemented analogous to TAstVisitor
|
// Initial setup of the dispatch table.
|
||||||
|
// The base implementation maps all kinds to the legacy VisitXYZ virtual methods.
|
||||||
|
procedure SetupHandlers; virtual;
|
||||||
|
|
||||||
|
// The central dispatch method. Looks up the handler in the registry.
|
||||||
|
function Visit(const Node: IAstNode): T; virtual;
|
||||||
|
|
||||||
|
// Legacy Virtual Methods (kept for backward compatibility and default mapping)
|
||||||
|
// Subclasses should eventually move to RegisterHandler, but overriding these still works
|
||||||
|
// because SetupHandlers maps them by default.
|
||||||
function VisitConstant(const Node: IConstantNode): T; virtual;
|
function VisitConstant(const Node: IConstantNode): T; virtual;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): T; virtual;
|
function VisitIdentifier(const Node: IIdentifierNode): T; virtual;
|
||||||
function VisitKeyword(const Node: IKeywordNode): T; virtual;
|
function VisitKeyword(const Node: IKeywordNode): T; virtual;
|
||||||
@@ -129,8 +147,17 @@ type
|
|||||||
function VisitPipeSelectorList(const Node: IPipeSelectorList): T; virtual;
|
function VisitPipeSelectorList(const Node: IPipeSelectorList): T; virtual;
|
||||||
function VisitPipeInputList(const Node: IPipeInputList): T; virtual;
|
function VisitPipeInputList(const Node: IPipeInputList): T; virtual;
|
||||||
function VisitPipe(const Node: IPipeNode): T; virtual;
|
function VisitPipe(const Node: IPipeNode): T; virtual;
|
||||||
|
|
||||||
|
// Bridge to support calling Accept on node directly (double dispatch pattern)
|
||||||
|
// In the new architecture, we prefer calling Visit(Node) directly.
|
||||||
|
function Accept(const Node: IAstNode): T; virtual;
|
||||||
|
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Helper for transformation visitors (returns IAstNode)
|
||||||
|
// Overrides legacy methods to provide default recursive reconstruction behavior.
|
||||||
TAstTransformer = class abstract(TAstVisitor<IAstNode>)
|
TAstTransformer = class abstract(TAstVisitor<IAstNode>)
|
||||||
protected
|
protected
|
||||||
function VisitConstant(const Node: IConstantNode): IAstNode; override;
|
function VisitConstant(const Node: IConstantNode): IAstNode; override;
|
||||||
@@ -179,12 +206,91 @@ implementation
|
|||||||
|
|
||||||
{ TAstVisitor<T> }
|
{ TAstVisitor<T> }
|
||||||
|
|
||||||
|
constructor TAstVisitor<T>.Create;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
SetupHandlers;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstVisitor<T>.RegisterHandler(Kind: TAstNodeKind; Handler: TNodeHandler<T>);
|
||||||
|
begin
|
||||||
|
FHandlers[Kind] := Handler;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstVisitor<T>.SetupHandlers;
|
||||||
|
begin
|
||||||
|
// Map all kinds to the legacy virtual methods.
|
||||||
|
// This provides the compatibility layer for existing subclasses.
|
||||||
|
// In Phase 2, subclasses will register their own handlers directly here.
|
||||||
|
|
||||||
|
// Core
|
||||||
|
FHandlers[akConstant] := function(const Node: IAstNode): T begin Result := VisitConstant(Node.AsConstant); end;
|
||||||
|
FHandlers[akIdentifier] := function(const Node: IAstNode): T begin Result := VisitIdentifier(Node.AsIdentifier); end;
|
||||||
|
FHandlers[akKeyword] := function(const Node: IAstNode): T begin Result := VisitKeyword(Node.AsKeyword); end;
|
||||||
|
|
||||||
|
// Lists
|
||||||
|
FHandlers[akParameterList] := function(const Node: IAstNode): T begin Result := VisitParameterList(Node.AsParameterList); end;
|
||||||
|
FHandlers[akArgumentList] := function(const Node: IAstNode): T begin Result := VisitArgumentList(Node.AsArgumentList); end;
|
||||||
|
FHandlers[akExpressionList] := function(const Node: IAstNode): T begin Result := VisitExpressionList(Node.AsExpressionList); end;
|
||||||
|
FHandlers[akRecordFieldList] := function(const Node: IAstNode): T begin Result := VisitRecordFieldList(Node.AsRecordFieldList); end;
|
||||||
|
FHandlers[akRecordField] := function(const Node: IAstNode): T begin Result := VisitRecordField(Node.AsRecordField); end;
|
||||||
|
|
||||||
|
// Structural
|
||||||
|
FHandlers[akIfExpression] := function(const Node: IAstNode): T begin Result := VisitIfExpression(Node.AsIfExpression); end;
|
||||||
|
FHandlers[akCondExpression] := function(const Node: IAstNode): T begin Result := VisitCondExpression(Node.AsCondExpression); end;
|
||||||
|
FHandlers[akLambdaExpression] := function(const Node: IAstNode): T begin Result := VisitLambdaExpression(Node.AsLambdaExpression); end;
|
||||||
|
FHandlers[akFunctionCall] := function(const Node: IAstNode): T begin Result := VisitFunctionCall(Node.AsFunctionCall); end;
|
||||||
|
FHandlers[akMacroExpansion] := function(const Node: IAstNode): T begin Result := VisitMacroExpansionNode(Node.AsMacroExpansion); end;
|
||||||
|
FHandlers[akBlockExpression] := function(const Node: IAstNode): T begin Result := VisitBlockExpression(Node.AsBlockExpression); end;
|
||||||
|
FHandlers[akVariableDeclaration] :=
|
||||||
|
function(const Node: IAstNode): T begin Result := VisitVariableDeclaration(Node.AsVariableDeclaration); end;
|
||||||
|
FHandlers[akAssignment] := function(const Node: IAstNode): T begin Result := VisitAssignment(Node.AsAssignment); end;
|
||||||
|
FHandlers[akMacroDefinition] := function(const Node: IAstNode): T begin Result := VisitMacroDefinition(Node.AsMacroDefinition); end;
|
||||||
|
FHandlers[akQuasiquote] := function(const Node: IAstNode): T begin Result := VisitQuasiquote(Node.AsQuasiquote); end;
|
||||||
|
FHandlers[akUnquote] := function(const Node: IAstNode): T begin Result := VisitUnquote(Node.AsUnquote); end;
|
||||||
|
FHandlers[akUnquoteSplicing] := function(const Node: IAstNode): T begin Result := VisitUnquoteSplicing(Node.AsUnquoteSplicing); end;
|
||||||
|
FHandlers[akIndexer] := function(const Node: IAstNode): T begin Result := VisitIndexer(Node.AsIndexer); end;
|
||||||
|
FHandlers[akMemberAccess] := function(const Node: IAstNode): T begin Result := VisitMemberAccess(Node.AsMemberAccess); end;
|
||||||
|
FHandlers[akRecordLiteral] := function(const Node: IAstNode): T begin Result := VisitRecordLiteral(Node.AsRecordLiteral); end;
|
||||||
|
FHandlers[akCreateSeries] := function(const Node: IAstNode): T begin Result := VisitCreateSeries(Node.AsCreateSeries); end;
|
||||||
|
FHandlers[akAddSeriesItem] := function(const Node: IAstNode): T begin Result := VisitAddSeriesItem(Node.AsAddSeriesItem); end;
|
||||||
|
FHandlers[akSeriesLength] := function(const Node: IAstNode): T begin Result := VisitSeriesLength(Node.AsSeriesLength); end;
|
||||||
|
FHandlers[akRecur] := function(const Node: IAstNode): T begin Result := VisitRecurNode(Node.AsRecur); end;
|
||||||
|
FHandlers[akNop] := function(const Node: IAstNode): T begin Result := VisitNop(Node.AsNop); end;
|
||||||
|
|
||||||
|
// Pipes
|
||||||
|
FHandlers[akPipeInput] := function(const Node: IAstNode): T begin Result := VisitPipeInput(Node.AsPipeInput); end;
|
||||||
|
FHandlers[akPipeSelectorList] := function(const Node: IAstNode): T begin Result := VisitPipeSelectorList(Node.AsPipeSelectorList); end;
|
||||||
|
FHandlers[akPipeInputList] := function(const Node: IAstNode): T begin Result := VisitPipeInputList(Node.AsPipeInputList); end;
|
||||||
|
FHandlers[akPipe] := function(const Node: IAstNode): T begin Result := VisitPipe(Node.AsPipe); end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisitor<T>.Visit(const Node: IAstNode): T;
|
||||||
|
var
|
||||||
|
handler: TNodeHandler<T>;
|
||||||
|
begin
|
||||||
|
if not Assigned(Node) then
|
||||||
|
Exit(Default(T));
|
||||||
|
|
||||||
|
// O(1) Lookup
|
||||||
|
handler := FHandlers[Node.Kind];
|
||||||
|
|
||||||
|
if Assigned(handler) then
|
||||||
|
Result := handler(Node)
|
||||||
|
else
|
||||||
|
raise ENoHandlerException.Create(Node.Kind.ToString);
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.Accept(const Node: IAstNode): T;
|
function TAstVisitor<T>.Accept(const Node: IAstNode): T;
|
||||||
begin
|
begin
|
||||||
if Assigned(Node) then
|
Result := Visit(Node);
|
||||||
Result := Node.Accept(Self).AsGeneric<T>
|
end;
|
||||||
else
|
|
||||||
Result := Default(T);
|
// --- Interface Bridge Methods (IAstVisitor -> TDataValue) ---
|
||||||
|
|
||||||
|
function TAstVisitor<T>.VisitBridge(const Node: IAstNode): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := TDataValue.FromGeneric<T>(Visit(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitConstant(const Node: IConstantNode): TDataValue;
|
function TAstVisitor<T>.DoVisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
@@ -199,7 +305,6 @@ function TAstVisitor<T>.DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
|||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitKeyword(Node));
|
Result := TDataValue.FromGeneric<T>(VisitKeyword(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitParameterList(const Node: IParameterList): TDataValue;
|
function TAstVisitor<T>.DoVisitParameterList(const Node: IParameterList): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitParameterList(Node));
|
Result := TDataValue.FromGeneric<T>(VisitParameterList(Node));
|
||||||
@@ -220,7 +325,6 @@ function TAstVisitor<T>.DoVisitRecordField(const Node: IRecordFieldNode): TDataV
|
|||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitRecordField(Node));
|
Result := TDataValue.FromGeneric<T>(VisitRecordField(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function TAstVisitor<T>.DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitIfExpression(Node));
|
Result := TDataValue.FromGeneric<T>(VisitIfExpression(Node));
|
||||||
@@ -301,7 +405,6 @@ function TAstVisitor<T>.DoVisitNop(const Node: INopNode): TDataValue;
|
|||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitNop(Node));
|
Result := TDataValue.FromGeneric<T>(VisitNop(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitPipeInput(const Node: IPipeInputNode): TDataValue;
|
function TAstVisitor<T>.DoVisitPipeInput(const Node: IPipeInputNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitPipeInput(Node));
|
Result := TDataValue.FromGeneric<T>(VisitPipeInput(Node));
|
||||||
@@ -319,7 +422,7 @@ begin
|
|||||||
Result := TDataValue.FromGeneric<T>(VisitPipe(Node));
|
Result := TDataValue.FromGeneric<T>(VisitPipe(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Default implementations (analogous to TAstVisitor) ---
|
// --- Default implementations (analogous to original abstract class stubs) ---
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitConstant(const Node: IConstantNode): T;
|
function TAstVisitor<T>.VisitConstant(const Node: IConstantNode): T;
|
||||||
begin
|
begin
|
||||||
@@ -340,43 +443,43 @@ function TAstVisitor<T>.VisitParameterList(const Node: IParameterList): T;
|
|||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
for var Item in Node do
|
for var Item in Node do
|
||||||
Accept(Item);
|
Visit(Item);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitArgumentList(const Node: IArgumentList): T;
|
function TAstVisitor<T>.VisitArgumentList(const Node: IArgumentList): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
for var Item in Node do
|
for var Item in Node do
|
||||||
Accept(Item);
|
Visit(Item);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitExpressionList(const Node: IExpressionList): T;
|
function TAstVisitor<T>.VisitExpressionList(const Node: IExpressionList): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
for var Item in Node do
|
for var Item in Node do
|
||||||
Accept(Item);
|
Visit(Item);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitRecordFieldList(const Node: IRecordFieldList): T;
|
function TAstVisitor<T>.VisitRecordFieldList(const Node: IRecordFieldList): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
for var Item in Node do
|
for var Item in Node do
|
||||||
Accept(Item);
|
Visit(Item);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitRecordField(const Node: IRecordFieldNode): T;
|
function TAstVisitor<T>.VisitRecordField(const Node: IRecordFieldNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Key);
|
Visit(Node.Key);
|
||||||
Accept(Node.Value);
|
Visit(Node.Value);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitIfExpression(const Node: IIfExpressionNode): T;
|
function TAstVisitor<T>.VisitIfExpression(const Node: IIfExpressionNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Condition);
|
Visit(Node.Condition);
|
||||||
Accept(Node.ThenBranch);
|
Visit(Node.ThenBranch);
|
||||||
Accept(Node.ElseBranch);
|
Visit(Node.ElseBranch);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitCondExpression(const Node: ICondExpressionNode): T;
|
function TAstVisitor<T>.VisitCondExpression(const Node: ICondExpressionNode): T;
|
||||||
@@ -386,97 +489,97 @@ begin
|
|||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
for pair in Node.Pairs do
|
for pair in Node.Pairs do
|
||||||
begin
|
begin
|
||||||
Accept(pair.Condition);
|
Visit(pair.Condition);
|
||||||
Accept(pair.Branch);
|
Visit(pair.Branch);
|
||||||
end;
|
end;
|
||||||
Accept(Node.ElseBranch);
|
Visit(Node.ElseBranch);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitLambdaExpression(const Node: ILambdaExpressionNode): T;
|
function TAstVisitor<T>.VisitLambdaExpression(const Node: ILambdaExpressionNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Parameters);
|
Visit(Node.Parameters);
|
||||||
Accept(Node.Body);
|
Visit(Node.Body);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitFunctionCall(const Node: IFunctionCallNode): T;
|
function TAstVisitor<T>.VisitFunctionCall(const Node: IFunctionCallNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Callee);
|
Visit(Node.Callee);
|
||||||
Accept(Node.Arguments);
|
Visit(Node.Arguments);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitMacroExpansionNode(const Node: IMacroExpansionNode): T;
|
function TAstVisitor<T>.VisitMacroExpansionNode(const Node: IMacroExpansionNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.CallNode);
|
Visit(Node.CallNode);
|
||||||
Accept(Node.ExpandedBody);
|
Visit(Node.ExpandedBody);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitBlockExpression(const Node: IBlockExpressionNode): T;
|
function TAstVisitor<T>.VisitBlockExpression(const Node: IBlockExpressionNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Expressions);
|
Visit(Node.Expressions);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitVariableDeclaration(const Node: IVariableDeclarationNode): T;
|
function TAstVisitor<T>.VisitVariableDeclaration(const Node: IVariableDeclarationNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Target);
|
Visit(Node.Target);
|
||||||
Accept(Node.Initializer);
|
Visit(Node.Initializer);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitAssignment(const Node: IAssignmentNode): T;
|
function TAstVisitor<T>.VisitAssignment(const Node: IAssignmentNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Target);
|
Visit(Node.Target);
|
||||||
Accept(Node.Value);
|
Visit(Node.Value);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitMacroDefinition(const Node: IMacroDefinitionNode): T;
|
function TAstVisitor<T>.VisitMacroDefinition(const Node: IMacroDefinitionNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Name);
|
Visit(Node.Name);
|
||||||
Accept(Node.Parameters);
|
Visit(Node.Parameters);
|
||||||
Accept(Node.Body);
|
Visit(Node.Body);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitQuasiquote(const Node: IQuasiquoteNode): T;
|
function TAstVisitor<T>.VisitQuasiquote(const Node: IQuasiquoteNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Expression);
|
Visit(Node.Expression);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitUnquote(const Node: IUnquoteNode): T;
|
function TAstVisitor<T>.VisitUnquote(const Node: IUnquoteNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Expression);
|
Visit(Node.Expression);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): T;
|
function TAstVisitor<T>.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Expression);
|
Visit(Node.Expression);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitIndexer(const Node: IIndexerNode): T;
|
function TAstVisitor<T>.VisitIndexer(const Node: IIndexerNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Base);
|
Visit(Node.Base);
|
||||||
Accept(Node.Index);
|
Visit(Node.Index);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitMemberAccess(const Node: IMemberAccessNode): T;
|
function TAstVisitor<T>.VisitMemberAccess(const Node: IMemberAccessNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Base);
|
Visit(Node.Base);
|
||||||
Accept(Node.Member);
|
Visit(Node.Member);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitRecordLiteral(const Node: IRecordLiteralNode): T;
|
function TAstVisitor<T>.VisitRecordLiteral(const Node: IRecordLiteralNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Fields);
|
Visit(Node.Fields);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitCreateSeries(const Node: ICreateSeriesNode): T;
|
function TAstVisitor<T>.VisitCreateSeries(const Node: ICreateSeriesNode): T;
|
||||||
@@ -487,21 +590,21 @@ end;
|
|||||||
function TAstVisitor<T>.VisitAddSeriesItem(const Node: IAddSeriesItemNode): T;
|
function TAstVisitor<T>.VisitAddSeriesItem(const Node: IAddSeriesItemNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Series);
|
Visit(Node.Series);
|
||||||
Accept(Node.Value);
|
Visit(Node.Value);
|
||||||
Accept(Node.Lookback);
|
Visit(Node.Lookback);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitSeriesLength(const Node: ISeriesLengthNode): T;
|
function TAstVisitor<T>.VisitSeriesLength(const Node: ISeriesLengthNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Series);
|
Visit(Node.Series);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitRecurNode(const Node: IRecurNode): T;
|
function TAstVisitor<T>.VisitRecurNode(const Node: IRecurNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Arguments);
|
Visit(Node.Arguments);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitNop(const Node: INopNode): T;
|
function TAstVisitor<T>.VisitNop(const Node: INopNode): T;
|
||||||
@@ -512,29 +615,29 @@ end;
|
|||||||
function TAstVisitor<T>.VisitPipeInput(const Node: IPipeInputNode): T;
|
function TAstVisitor<T>.VisitPipeInput(const Node: IPipeInputNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.StreamSource);
|
Visit(Node.StreamSource);
|
||||||
Accept(Node.Selectors); // Now visits SelectorList
|
Visit(Node.Selectors);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitPipeSelectorList(const Node: IPipeSelectorList): T;
|
function TAstVisitor<T>.VisitPipeSelectorList(const Node: IPipeSelectorList): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
for var Item in Node do
|
for var Item in Node do
|
||||||
Accept(Item);
|
Visit(Item);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitPipeInputList(const Node: IPipeInputList): T;
|
function TAstVisitor<T>.VisitPipeInputList(const Node: IPipeInputList): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
for var Item in Node do
|
for var Item in Node do
|
||||||
Accept(Item);
|
Visit(Item);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.VisitPipe(const Node: IPipeNode): T;
|
function TAstVisitor<T>.VisitPipe(const Node: IPipeNode): T;
|
||||||
begin
|
begin
|
||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
Accept(Node.Inputs);
|
Visit(Node.Inputs);
|
||||||
Accept(Node.Transformation);
|
Visit(Node.Transformation);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TAstTransformer }
|
{ TAstTransformer }
|
||||||
@@ -580,7 +683,7 @@ begin
|
|||||||
for i := 0 to Node.Count - 1 do
|
for i := 0 to Node.Count - 1 do
|
||||||
begin
|
begin
|
||||||
item := Node[i];
|
item := Node[i];
|
||||||
newItem := Accept(item).AsIdentifier;
|
newItem := Visit(item).AsIdentifier;
|
||||||
newItems[i] := newItem;
|
newItems[i] := newItem;
|
||||||
if item <> newItem then
|
if item <> newItem then
|
||||||
hasChanged := True;
|
hasChanged := True;
|
||||||
@@ -605,7 +708,7 @@ begin
|
|||||||
for i := 0 to Node.Count - 1 do
|
for i := 0 to Node.Count - 1 do
|
||||||
begin
|
begin
|
||||||
item := Node[i];
|
item := Node[i];
|
||||||
newItem := Accept(item);
|
newItem := Visit(item);
|
||||||
newItems[i] := newItem;
|
newItems[i] := newItem;
|
||||||
if item <> newItem then
|
if item <> newItem then
|
||||||
hasChanged := True;
|
hasChanged := True;
|
||||||
@@ -629,7 +732,7 @@ begin
|
|||||||
for i := 0 to Node.Count - 1 do
|
for i := 0 to Node.Count - 1 do
|
||||||
begin
|
begin
|
||||||
item := Node[i];
|
item := Node[i];
|
||||||
newItem := Accept(item);
|
newItem := Visit(item);
|
||||||
newItems[i] := newItem;
|
newItems[i] := newItem;
|
||||||
if item <> newItem then
|
if item <> newItem then
|
||||||
hasChanged := True;
|
hasChanged := True;
|
||||||
@@ -653,8 +756,8 @@ begin
|
|||||||
for i := 0 to Node.Count - 1 do
|
for i := 0 to Node.Count - 1 do
|
||||||
begin
|
begin
|
||||||
item := Node[i];
|
item := Node[i];
|
||||||
// Ensure we transform the field node itself via Accept to trigger VisitRecordField
|
// Ensure we transform the field node itself via Visit to trigger VisitRecordField
|
||||||
newItem := Accept(item).AsRecordField;
|
newItem := Visit(item).AsRecordField;
|
||||||
newItems[i] := newItem;
|
newItems[i] := newItem;
|
||||||
if item <> newItem then
|
if item <> newItem then
|
||||||
hasChanged := True;
|
hasChanged := True;
|
||||||
@@ -671,8 +774,8 @@ var
|
|||||||
newKey: IKeywordNode;
|
newKey: IKeywordNode;
|
||||||
newValue: IAstNode;
|
newValue: IAstNode;
|
||||||
begin
|
begin
|
||||||
newKey := Accept(Node.Key).AsKeyword;
|
newKey := Visit(Node.Key).AsKeyword;
|
||||||
newValue := Accept(Node.Value);
|
newValue := Visit(Node.Value);
|
||||||
|
|
||||||
if (newKey = Node.Key) and (newValue = Node.Value) then
|
if (newKey = Node.Key) and (newValue = Node.Value) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -686,9 +789,9 @@ function TAstTransformer.VisitIfExpression(const Node: IIfExpressionNode): IAstN
|
|||||||
var
|
var
|
||||||
newCond, newThen, newElse: IAstNode;
|
newCond, newThen, newElse: IAstNode;
|
||||||
begin
|
begin
|
||||||
newCond := Accept(Node.Condition);
|
newCond := Visit(Node.Condition);
|
||||||
newThen := Accept(Node.ThenBranch);
|
newThen := Visit(Node.ThenBranch);
|
||||||
newElse := Accept(Node.ElseBranch);
|
newElse := Visit(Node.ElseBranch);
|
||||||
|
|
||||||
if (newCond = Node.Condition) and (newThen = Node.ThenBranch) and (newElse = Node.ElseBranch) then
|
if (newCond = Node.Condition) and (newThen = Node.ThenBranch) and (newElse = Node.ElseBranch) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -709,15 +812,15 @@ begin
|
|||||||
|
|
||||||
for i := 0 to High(Node.Pairs) do
|
for i := 0 to High(Node.Pairs) do
|
||||||
begin
|
begin
|
||||||
newCond := Accept(Node.Pairs[i].Condition);
|
newCond := Visit(Node.Pairs[i].Condition);
|
||||||
newBranch := Accept(Node.Pairs[i].Branch);
|
newBranch := Visit(Node.Pairs[i].Branch);
|
||||||
newPairs[i] := TCondPair.Create(newCond, newBranch);
|
newPairs[i] := TCondPair.Create(newCond, newBranch);
|
||||||
|
|
||||||
if (newCond <> Node.Pairs[i].Condition) or (newBranch <> Node.Pairs[i].Branch) then
|
if (newCond <> Node.Pairs[i].Condition) or (newBranch <> Node.Pairs[i].Branch) then
|
||||||
hasChanged := True;
|
hasChanged := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
newElse := Accept(Node.ElseBranch); // Accept handles nil
|
newElse := Visit(Node.ElseBranch); // Visit handles nil
|
||||||
if newElse <> Node.ElseBranch then
|
if newElse <> Node.ElseBranch then
|
||||||
hasChanged := True;
|
hasChanged := True;
|
||||||
|
|
||||||
@@ -732,8 +835,8 @@ var
|
|||||||
newParams: IParameterList;
|
newParams: IParameterList;
|
||||||
newBody: IAstNode;
|
newBody: IAstNode;
|
||||||
begin
|
begin
|
||||||
newParams := Accept(Node.Parameters).AsParameterList;
|
newParams := Visit(Node.Parameters).AsParameterList;
|
||||||
newBody := Accept(Node.Body);
|
newBody := Visit(Node.Body);
|
||||||
|
|
||||||
if (newParams = Node.Parameters) and (newBody = Node.Body) then
|
if (newParams = Node.Parameters) and (newBody = Node.Body) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -761,8 +864,8 @@ var
|
|||||||
newCallee: IAstNode;
|
newCallee: IAstNode;
|
||||||
newArgs: IArgumentList;
|
newArgs: IArgumentList;
|
||||||
begin
|
begin
|
||||||
newCallee := Accept(Node.Callee);
|
newCallee := Visit(Node.Callee);
|
||||||
newArgs := Accept(Node.Arguments).AsArgumentList;
|
newArgs := Visit(Node.Arguments).AsArgumentList;
|
||||||
|
|
||||||
if (newCallee = Node.Callee) and (newArgs = Node.Arguments) then
|
if (newCallee = Node.Callee) and (newArgs = Node.Arguments) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -778,7 +881,7 @@ function TAstTransformer.VisitMacroExpansionNode(const Node: IMacroExpansionNode
|
|||||||
var
|
var
|
||||||
newBody: IAstNode;
|
newBody: IAstNode;
|
||||||
begin
|
begin
|
||||||
newBody := Accept(Node.ExpandedBody);
|
newBody := Visit(Node.ExpandedBody);
|
||||||
if newBody = Node.ExpandedBody then
|
if newBody = Node.ExpandedBody then
|
||||||
exit(Node);
|
exit(Node);
|
||||||
|
|
||||||
@@ -791,7 +894,7 @@ function TAstTransformer.VisitBlockExpression(const Node: IBlockExpressionNode):
|
|||||||
var
|
var
|
||||||
newExprs: IExpressionList;
|
newExprs: IExpressionList;
|
||||||
begin
|
begin
|
||||||
newExprs := Accept(Node.Expressions).AsExpressionList;
|
newExprs := Visit(Node.Expressions).AsExpressionList;
|
||||||
|
|
||||||
if newExprs = Node.Expressions then
|
if newExprs = Node.Expressions then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -805,8 +908,8 @@ var
|
|||||||
newTarget: IAstNode;
|
newTarget: IAstNode;
|
||||||
newInit: IAstNode;
|
newInit: IAstNode;
|
||||||
begin
|
begin
|
||||||
newTarget := Accept(Node.Target);
|
newTarget := Visit(Node.Target);
|
||||||
newInit := Accept(Node.Initializer);
|
newInit := Visit(Node.Initializer);
|
||||||
|
|
||||||
if (newTarget = Node.Target) and (newInit = Node.Initializer) then
|
if (newTarget = Node.Target) and (newInit = Node.Initializer) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -821,8 +924,8 @@ var
|
|||||||
newTarget: IAstNode;
|
newTarget: IAstNode;
|
||||||
newValue: IAstNode;
|
newValue: IAstNode;
|
||||||
begin
|
begin
|
||||||
newTarget := Accept(Node.Target);
|
newTarget := Visit(Node.Target);
|
||||||
newValue := Accept(Node.Value);
|
newValue := Visit(Node.Value);
|
||||||
|
|
||||||
if (newTarget = Node.Target) and (newValue = Node.Value) then
|
if (newTarget = Node.Target) and (newValue = Node.Value) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -841,7 +944,7 @@ function TAstTransformer.VisitQuasiquote(const Node: IQuasiquoteNode): IAstNode;
|
|||||||
var
|
var
|
||||||
newExpr: IAstNode;
|
newExpr: IAstNode;
|
||||||
begin
|
begin
|
||||||
newExpr := Accept(Node.Expression);
|
newExpr := Visit(Node.Expression);
|
||||||
if newExpr = Node.Expression then
|
if newExpr = Node.Expression then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
@@ -852,7 +955,7 @@ function TAstTransformer.VisitUnquote(const Node: IUnquoteNode): IAstNode;
|
|||||||
var
|
var
|
||||||
newExpr: IAstNode;
|
newExpr: IAstNode;
|
||||||
begin
|
begin
|
||||||
newExpr := Accept(Node.Expression);
|
newExpr := Visit(Node.Expression);
|
||||||
if newExpr = Node.Expression then
|
if newExpr = Node.Expression then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
@@ -863,7 +966,7 @@ function TAstTransformer.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode):
|
|||||||
var
|
var
|
||||||
newExpr: IAstNode;
|
newExpr: IAstNode;
|
||||||
begin
|
begin
|
||||||
newExpr := Accept(Node.Expression);
|
newExpr := Visit(Node.Expression);
|
||||||
|
|
||||||
if (newExpr = Node.Expression) then
|
if (newExpr = Node.Expression) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -875,8 +978,8 @@ function TAstTransformer.VisitIndexer(const Node: IIndexerNode): IAstNode;
|
|||||||
var
|
var
|
||||||
newBase, newIndex: IAstNode;
|
newBase, newIndex: IAstNode;
|
||||||
begin
|
begin
|
||||||
newBase := Accept(Node.Base);
|
newBase := Visit(Node.Base);
|
||||||
newIndex := Accept(Node.Index);
|
newIndex := Visit(Node.Index);
|
||||||
|
|
||||||
if (newBase = Node.Base) and (newIndex = Node.Index) then
|
if (newBase = Node.Base) and (newIndex = Node.Index) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -889,8 +992,8 @@ var
|
|||||||
newBase: IAstNode;
|
newBase: IAstNode;
|
||||||
newMember: IKeywordNode;
|
newMember: IKeywordNode;
|
||||||
begin
|
begin
|
||||||
newBase := Accept(Node.Base);
|
newBase := Visit(Node.Base);
|
||||||
newMember := Accept(Node.Member).AsKeyword;
|
newMember := Visit(Node.Member).AsKeyword;
|
||||||
|
|
||||||
if (newBase = Node.Base) and (newMember = Node.Member) then
|
if (newBase = Node.Base) and (newMember = Node.Member) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -902,7 +1005,7 @@ function TAstTransformer.VisitRecordLiteral(const Node: IRecordLiteralNode): IAs
|
|||||||
var
|
var
|
||||||
newFields: IRecordFieldList;
|
newFields: IRecordFieldList;
|
||||||
begin
|
begin
|
||||||
newFields := Accept(Node.Fields).AsRecordFieldList;
|
newFields := Visit(Node.Fields).AsRecordFieldList;
|
||||||
|
|
||||||
if newFields = Node.Fields then
|
if newFields = Node.Fields then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -917,9 +1020,9 @@ var
|
|||||||
newSeries: IIdentifierNode;
|
newSeries: IIdentifierNode;
|
||||||
newValue, newLookback: IAstNode;
|
newValue, newLookback: IAstNode;
|
||||||
begin
|
begin
|
||||||
newSeries := Accept(Node.Series).AsIdentifier;
|
newSeries := Visit(Node.Series).AsIdentifier;
|
||||||
newValue := Accept(Node.Value);
|
newValue := Visit(Node.Value);
|
||||||
newLookback := Accept(Node.Lookback);
|
newLookback := Visit(Node.Lookback);
|
||||||
|
|
||||||
if (newSeries = Node.Series) and (newValue = Node.Value) and (newLookback = Node.Lookback) then
|
if (newSeries = Node.Series) and (newValue = Node.Value) and (newLookback = Node.Lookback) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -931,7 +1034,7 @@ function TAstTransformer.VisitSeriesLength(const Node: ISeriesLengthNode): IAstN
|
|||||||
var
|
var
|
||||||
newSeries: IIdentifierNode;
|
newSeries: IIdentifierNode;
|
||||||
begin
|
begin
|
||||||
newSeries := Accept(Node.Series).AsIdentifier;
|
newSeries := Visit(Node.Series).AsIdentifier;
|
||||||
|
|
||||||
if newSeries = Node.Series then
|
if newSeries = Node.Series then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -943,7 +1046,7 @@ function TAstTransformer.VisitRecurNode(const Node: IRecurNode): IAstNode;
|
|||||||
var
|
var
|
||||||
newArgs: IArgumentList;
|
newArgs: IArgumentList;
|
||||||
begin
|
begin
|
||||||
newArgs := Accept(Node.Arguments).AsArgumentList;
|
newArgs := Visit(Node.Arguments).AsArgumentList;
|
||||||
|
|
||||||
if newArgs = Node.Arguments then
|
if newArgs = Node.Arguments then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -956,8 +1059,8 @@ var
|
|||||||
newSource: IIdentifierNode;
|
newSource: IIdentifierNode;
|
||||||
newSels: IPipeSelectorList;
|
newSels: IPipeSelectorList;
|
||||||
begin
|
begin
|
||||||
newSource := Accept(Node.StreamSource).AsIdentifier;
|
newSource := Visit(Node.StreamSource).AsIdentifier;
|
||||||
newSels := Accept(Node.Selectors).AsPipeSelectorList;
|
newSels := Visit(Node.Selectors).AsPipeSelectorList;
|
||||||
|
|
||||||
if (newSource = Node.StreamSource) and (newSels = Node.Selectors) then
|
if (newSource = Node.StreamSource) and (newSels = Node.Selectors) then
|
||||||
Result := Node
|
Result := Node
|
||||||
@@ -977,7 +1080,7 @@ begin
|
|||||||
for i := 0 to Node.Count - 1 do
|
for i := 0 to Node.Count - 1 do
|
||||||
begin
|
begin
|
||||||
item := Node[i];
|
item := Node[i];
|
||||||
newItem := Accept(item).AsKeyword;
|
newItem := Visit(item).AsKeyword;
|
||||||
newItems[i] := newItem;
|
newItems[i] := newItem;
|
||||||
if item <> newItem then
|
if item <> newItem then
|
||||||
hasChanged := True;
|
hasChanged := True;
|
||||||
@@ -1002,7 +1105,7 @@ begin
|
|||||||
for i := 0 to Node.Count - 1 do
|
for i := 0 to Node.Count - 1 do
|
||||||
begin
|
begin
|
||||||
item := Node[i];
|
item := Node[i];
|
||||||
newItem := Accept(item).AsPipeInput; // Explicit cast via new helper
|
newItem := Visit(item).AsPipeInput; // Explicit cast via new helper
|
||||||
newItems[i] := newItem;
|
newItems[i] := newItem;
|
||||||
if item <> newItem then
|
if item <> newItem then
|
||||||
hasChanged := True;
|
hasChanged := True;
|
||||||
@@ -1021,8 +1124,8 @@ var
|
|||||||
newInputs: IPipeInputList;
|
newInputs: IPipeInputList;
|
||||||
newTrans: ILambdaExpressionNode;
|
newTrans: ILambdaExpressionNode;
|
||||||
begin
|
begin
|
||||||
newInputs := Accept(Node.Inputs).AsPipeInputList;
|
newInputs := Visit(Node.Inputs).AsPipeInputList;
|
||||||
newTrans := Accept(Node.Transformation).AsLambdaExpression;
|
newTrans := Visit(Node.Transformation).AsLambdaExpression;
|
||||||
|
|
||||||
if (newInputs = Node.Inputs) and (newTrans = Node.Transformation) then
|
if (newInputs = Node.Inputs) and (newTrans = Node.Transformation) then
|
||||||
Result := Node
|
Result := Node
|
||||||
|
|||||||
Reference in New Issue
Block a user