AST list refactoring

This commit is contained in:
Michael Schimmel
2026-01-04 22:41:44 +01:00
parent 2a7e6626ad
commit 242ec9a56e
27 changed files with 815 additions and 1076 deletions
+44 -38
View File
@@ -29,14 +29,13 @@ type
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 VisitTuple(const N: ITupleNode): 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 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 VisitIndexer(const N: IIndexerNode): TDataValue; virtual;
@@ -92,18 +91,16 @@ 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
akTuple: Result := VisitTuple(Node.AsTuple);
akIfExpression: Result := VisitIfExpression(Node.AsIfExpression);
akCondExpression: Result := VisitCondExpression(Node.AsCondExpression);
akLambdaExpression: Result := VisitLambdaExpression(Node.AsLambdaExpression);
akFunctionCall: Result := VisitFunctionCall(Node.AsFunctionCall);
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);
@@ -182,12 +179,10 @@ 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]);
SetLength(elements, N.Count);
for i := 0 to N.Count - 1 do
elements[i] := Visit(N.Items[i]);
// Uses the implicit operator: TArray<TDataValue> -> TDataValue (vkTuple)
Result := elements;
@@ -233,7 +228,11 @@ begin
lambdaScope.SetValues(TResolvedAddress.Create(akLocalOrParent, 0, 0), TDataValue(closure));
for k := 0 to params.Count - 1 do
lambdaScope[params[k].Address] := ArgValues[k];
begin
// Parameters are guaranteed to be Identifiers by the Binder
var paramNode := params.Items[k].AsIdentifier;
lambdaScope[paramNode.Address] := ArgValues[k];
end;
bodyVisitor := visitorFactory(lambdaScope);
Result := bodyVisitor.Visit(N.Body);
@@ -246,13 +245,15 @@ var
calleeValue: TDataValue;
argValues: TArray<TDataValue>;
i: Integer;
argsTuple: ITupleNode;
begin
argsTuple := N.Arguments;
SetLength(argValues, argsTuple.Count);
for i := 0 to argsTuple.Count - 1 do
argValues[i] := Visit(argsTuple.Items[i]);
if Assigned(N.StaticTarget) then
begin
SetLength(argValues, N.Arguments.Count);
for i := 0 to N.Arguments.Count - 1 do
argValues[i] := Visit(N.Arguments[i]);
Result := N.StaticTarget(argValues);
if not N.IsTailCall then
HandleTCO(Result);
@@ -263,10 +264,6 @@ begin
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]);
if N.IsTailCall then
Result := TDataValue.FromGeneric<TThunk>(TThunk.Create(calleeValue, argValues, false))
else
@@ -281,27 +278,27 @@ function TEvaluatorVisitor.VisitRecurNode(const N: IRecurNode): TDataValue;
var
argValues: TArray<TDataValue>;
i: Integer;
argsTuple: ITupleNode;
begin
SetLength(argValues, N.Arguments.Count);
for i := 0 to N.Arguments.Count - 1 do
argValues[i] := Visit(N.Arguments[i]);
argsTuple := N.Arguments;
SetLength(argValues, argsTuple.Count);
for i := 0 to argsTuple.Count - 1 do
argValues[i] := Visit(argsTuple.Items[i]);
// The "self" function is always at Slot 0
var callee := FScope[TResolvedAddress.Create(akLocalOrParent, 0, 0)];
Result := TDataValue.FromGeneric<TThunk>(TThunk.Create(callee, argValues, true));
end;
function TEvaluatorVisitor.VisitBlockExpression(const N: IBlockExpressionNode): TDataValue;
begin
Result := Visit(N.Expressions);
end;
function TEvaluatorVisitor.VisitExpressionList(const N: IExpressionList): TDataValue;
var
exprs: ITupleNode;
i: Integer;
begin
exprs := N.Expressions;
Result := TDataValue.Void;
for i := 0 to N.Count - 1 do
Result := Visit(N[i]);
for i := 0 to exprs.Count - 1 do
Result := Visit(exprs.Items[i]);
end;
function TEvaluatorVisitor.VisitIfExpression(const N: IIfExpressionNode): TDataValue;
@@ -367,7 +364,7 @@ begin
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)
vkTuple:
begin
var tpl := base.AsTuple;
var i := idx.AsScalar.Value.AsInt64;
@@ -400,21 +397,30 @@ end;
function TEvaluatorVisitor.VisitRecordLiteral(const N: IRecordLiteralNode): TDataValue;
var
i: Integer;
fieldsTuple: ITupleNode;
begin
if Assigned(N.ScalarDefinition) then
begin
var vals: TArray<TScalar.TValue>;
SetLength(vals, N.Fields.Count);
for i := 0 to N.Fields.Count - 1 do
vals[i] := Visit(N.Fields[i].Value).AsScalar.Value;
fieldsTuple := N.Fields;
SetLength(vals, fieldsTuple.Count);
for i := 0 to fieldsTuple.Count - 1 do
begin
var field := fieldsTuple.Items[i].AsRecordField;
vals[i] := Visit(field.Value).AsScalar.Value;
end;
Result := TScalarRecord.Create(N.ScalarDefinition, vals);
end
else
begin
var fields: TArray<TPair<IKeyword, TDataValue>>;
SetLength(fields, N.Fields.Count);
for i := 0 to N.Fields.Count - 1 do
fields[i] := TPair<IKeyword, TDataValue>.Create(N.Fields[i].Key.Value, Visit(N.Fields[i].Value));
fieldsTuple := N.Fields;
SetLength(fields, fieldsTuple.Count);
for i := 0 to fieldsTuple.Count - 1 do
begin
var field := fieldsTuple.Items[i].AsRecordField;
fields[i] := TPair<IKeyword, TDataValue>.Create(field.Key.Value, Visit(field.Value));
end;
Result := TGenericRecord<TDataValue>.Create(fields);
end;
end;
@@ -459,7 +465,7 @@ begin
SetLength(config, N.Inputs.Count);
for i := 0 to N.Inputs.Count - 1 do
begin
inputNode := N.Inputs[i];
inputNode := N.Inputs.Items[i].AsPipeInput;
inputVal := FScope[inputNode.StreamSource.Address];
if (inputVal.Kind <> vkStream) then
raise EEvaluatorException.Create('Stream expected');
@@ -470,7 +476,7 @@ begin
SetLength(config[i], selectors.Count);
for var k := 0 to selectors.Count - 1 do
begin
var key := selectors[k].Value;
var key := selectors.Items[k].AsKeyword.Value;
var idx := srcDef.IndexOf(key);
config[i][k] := TScalarRecordField.Create(key, srcDef[idx]);
end;