diff --git a/Src/AST/Myc.Ast.Evaluator.pas b/Src/AST/Myc.Ast.Evaluator.pas index eeca98d..35af716 100644 --- a/Src/AST/Myc.Ast.Evaluator.pas +++ b/Src/AST/Myc.Ast.Evaluator.pas @@ -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; 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; @@ -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. diff --git a/Src/AST/Myc.Ast.Visitor.pas b/Src/AST/Myc.Ast.Visitor.pas index 4999a63..30bfea5 100644 --- a/Src/AST/Myc.Ast.Visitor.pas +++ b/Src/AST/Myc.Ast.Visitor.pas @@ -14,8 +14,6 @@ uses type TAstVisitor = class; - // Handler signature is now strictly based on IAstNode to ensure binary compatibility - // with the dispatch array. TNodeHandler = reference to function(const Node: IAstNode): T; TAstVisitor = 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); 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) protected // Leaves