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
+19 -55
View File
@@ -24,11 +24,7 @@ type
function VisitVariableDeclaration(const Node: IAstNode): Boolean;
function VisitSeriesLength(const Node: IAstNode): Boolean;
// --- List Visitors (Aggregation Logic: All must be pure) ---
function VisitParameterList(const Node: IAstNode): Boolean;
function VisitArgumentList(const Node: IAstNode): Boolean;
function VisitExpressionList(const Node: IAstNode): Boolean;
function VisitRecordFieldList(const Node: IAstNode): Boolean;
// --- Elements ---
function VisitRecordField(const Node: IAstNode): Boolean;
// --- Critical Checks ---
@@ -55,9 +51,10 @@ type
function VisitMacroExpansionNode(const Node: IAstNode): Boolean;
function VisitNop(const Node: IAstNode): Boolean;
// Unification: Tuple (for [vectors], arguments, parameters, fields)
function VisitTuple(const Node: IAstNode): Boolean;
// Pipe Support (Structural Check)
// Pipe Support
function VisitPipeInput(const Node: IAstNode): Boolean;
function VisitPipeSelectorList(const Node: IAstNode): Boolean;
function VisitPipeInputList(const Node: IAstNode): Boolean;
@@ -105,11 +102,7 @@ begin
Register(akIdentifier, VisitIdentifier);
Register(akKeyword, VisitKeyword);
// Lists
Register(akParameterList, VisitParameterList);
Register(akArgumentList, VisitArgumentList);
Register(akExpressionList, VisitExpressionList);
Register(akRecordFieldList, VisitRecordFieldList);
// Elements
Register(akRecordField, VisitRecordField);
// Structural
@@ -134,6 +127,7 @@ begin
Register(akRecur, VisitRecurNode);
Register(akNop, VisitNop);
// Unified List Type
Register(akTuple, VisitTuple);
// Pipes
@@ -143,35 +137,20 @@ begin
Register(akPipe, VisitPipe);
end;
// --- List Visitors ---
// --- List / Container Visitors ---
function TPurityAnalyzer.VisitParameterList(const Node: IAstNode): Boolean;
function TPurityAnalyzer.VisitTuple(const Node: IAstNode): Boolean;
var
i: Integer;
T: ITupleNode;
begin
// Declarations are pure
Result := True;
end;
function TPurityAnalyzer.VisitArgumentList(const Node: IAstNode): Boolean;
begin
for var item in Node.AsArgumentList do
if not IsNodePure(item) then
exit(False);
Result := True;
end;
function TPurityAnalyzer.VisitExpressionList(const Node: IAstNode): Boolean;
begin
for var item in Node.AsExpressionList do
if not IsNodePure(item) then
exit(False);
Result := True;
end;
function TPurityAnalyzer.VisitRecordFieldList(const Node: IAstNode): Boolean;
begin
for var item in Node.AsRecordFieldList do
if not IsNodePure(item) then
T := Node.AsTuple;
// A tuple is pure if ALL its elements are pure.
for i := 0 to T.Count - 1 do
begin
if not IsNodePure(T.Items[i]) then
exit(False);
end;
Result := True;
end;
@@ -207,8 +186,6 @@ begin
// Accessing Parent/Upvalues (ScopeDepth > 0) makes the function state-dependent (closure state),
// effectively impure regarding referential transparency across different closure instances,
// unless we could prove the upvalue is constant (which we don't track yet).
// Note: Parameters are also ScopeDepth=0 in the Binder logic.
var I := Node.AsIdentifier;
Result := (I.Address.Kind = akLocalOrParent) and (I.Address.ScopeDepth = 0);
end;
@@ -222,7 +199,7 @@ begin
if not C.IsTargetPure then
exit(False);
// 2. All arguments must be pure expressions.
// 2. All arguments (Tuple) must be pure expressions.
Result := IsNodePure(C.Arguments);
end;
@@ -257,7 +234,7 @@ end;
function TPurityAnalyzer.VisitBlockExpression(const Node: IAstNode): Boolean;
begin
// Delegate to ExpressionList
// Delegate to Expression Tuple
Result := IsNodePure(Node.AsBlockExpression.Expressions);
end;
@@ -270,7 +247,7 @@ end;
function TPurityAnalyzer.VisitRecordLiteral(const Node: IAstNode): Boolean;
begin
// Delegate to RecordFieldList
// Delegate to Fields Tuple
Result := IsNodePure(Node.AsRecordLiteral.Fields);
end;
@@ -382,17 +359,4 @@ begin
Result := IsNodePure(P.Inputs) and IsNodePure(P.Transformation);
end;
function TPurityAnalyzer.VisitTuple(const Node: IAstNode): Boolean;
var
item: IAstNode;
begin
// Ein Tupel ist rein, wenn alle Elemente rein sind.
for item in Node.AsTuple.Elements do
begin
if not IsNodePure(item) then
exit(False);
end;
Result := True;
end;
end.