This commit is contained in:
Michael Schimmel
2026-01-04 18:48:04 +01:00
parent a4afae6f39
commit 991b998cb1
17 changed files with 534 additions and 102 deletions
+43 -13
View File
@@ -21,13 +21,16 @@ type
private
FScope: IExecutionScope;
protected
// Haupt-Dispatch-Methode
function Visit(const Node: IAstNode): TDataValue; virtual;
function CreateVisitorFactory: TEvaluatorFactory; virtual;
// Nur noch die für die Ausführung relevanten Methoden
// Besuchermethoden
function VisitConstant(const N: IConstantNode): TDataValue; virtual;
function VisitIdentifier(const N: IIdentifierNode): TDataValue; virtual;
function VisitKeyword(const N: IKeywordNode): TDataValue; virtual;
function VisitTuple(const N: ITupleNode): TDataValue; virtual; // <--- WICHTIG
function VisitIfExpression(const N: IIfExpressionNode): TDataValue; virtual;
function VisitCondExpression(const N: ICondExpressionNode): TDataValue; virtual;
function VisitLambdaExpression(const N: ILambdaExpressionNode): TDataValue; virtual;
@@ -89,10 +92,12 @@ end;
function TEvaluatorVisitor.Visit(const Node: IAstNode): TDataValue;
begin
// Der Hot-Path: Direkter Dispatch ohne Umweg über ungenutzte Methoden.
// HIER fehlte wahrscheinlich akTuple!
case Node.Kind of
akConstant: Result := VisitConstant(Node.AsConstant);
akIdentifier: Result := VisitIdentifier(Node.AsIdentifier);
akKeyword: Result := VisitKeyword(Node.AsKeyword);
akTuple: Result := VisitTuple(Node.AsTuple); // <--- KORREKTUR
akIfExpression: Result := VisitIfExpression(Node.AsIfExpression);
akCondExpression: Result := VisitCondExpression(Node.AsCondExpression);
akLambdaExpression: Result := VisitLambdaExpression(Node.AsLambdaExpression);
@@ -173,6 +178,21 @@ begin
Result := FScope[N.Address];
end;
function TEvaluatorVisitor.VisitTuple(const N: ITupleNode): TDataValue;
var
elements: TArray<TDataValue>;
i: Integer;
nodes: TArray<IAstNode>;
begin
nodes := N.Elements;
SetLength(elements, Length(nodes));
for i := 0 to High(nodes) do
elements[i] := Visit(nodes[i]);
// Uses the implicit operator: TArray<TDataValue> -> TDataValue (vkTuple)
Result := elements;
end;
function TEvaluatorVisitor.VisitLambdaExpression(const N: ILambdaExpressionNode): TDataValue;
var
capturedCells: TArray<IValueCell>;
@@ -334,20 +354,30 @@ begin
if base.IsVoid then
exit(TDataValue.Void);
idx := Visit(N.Index);
if (base.Kind = vkSeries) then
Result := TDataValue(base.AsSeries.Items[Integer(idx.AsScalar.Value.AsInt64)])
else if (base.Kind = vkRecordSeries) then
begin
var rs := base.AsRecordSeries;
var vals: TArray<TScalar.TValue>;
SetLength(vals, rs.Def.Count);
var i64 := idx.AsScalar.Value.AsInt64;
for var k := 0 to rs.Def.Count - 1 do
vals[k] := rs.Fields[rs.Def.Keywords[k]].Items[Integer(i64)].Value;
Result := TScalarRecord.Create(rs.Def, vals);
end
case base.Kind of
vkSeries: Result := TDataValue(base.AsSeries.Items[Integer(idx.AsScalar.Value.AsInt64)]);
vkRecordSeries:
begin
var rs := base.AsRecordSeries;
var vals: TArray<TScalar.TValue>;
SetLength(vals, rs.Def.Count);
var i64 := idx.AsScalar.Value.AsInt64;
for var k := 0 to rs.Def.Count - 1 do
vals[k] := rs.Fields[rs.Def.Keywords[k]].Items[Integer(i64)].Value;
Result := TScalarRecord.Create(rs.Def, vals);
end;
vkTuple: // <--- WICHTIG FÜR (get x 3)
begin
var tpl := base.AsTuple;
var i := idx.AsScalar.Value.AsInt64;
if (i < 0) or (i >= tpl.Count) then
raise EEvaluatorException.Create('Tuple index out of bounds');
Result := tpl.Items[Integer(i)];
end;
else
raise EEvaluatorException.Create('Indexer error');
end;
end;
function TEvaluatorVisitor.VisitMemberAccess(const N: IMemberAccessNode): TDataValue;