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
+25 -26
View File
@@ -437,7 +437,6 @@ begin
items.Add(ParseExpression.Node);
end;
// CHANGED: Use Tuple factory instead of ArgumentList
Result := TAst.Tuple(items.ToArray, startLoc);
finally
items.Free;
@@ -447,23 +446,19 @@ end;
function TParser.ExtractIdentifiers(const Node: IAstNode; const Context: string): TArray<IIdentifierNode>;
var
list: TArray<IAstNode>;
tuple: ITupleNode;
i: Integer;
begin
// Support both Tuple (new syntax [...]) and ArgumentList (internal legacy)
if Node.Kind = akTuple then
list := Node.AsTuple.Elements
else if Node.Kind = akArgumentList then
list := Node.AsArgumentList.ToArray
else
if Node.Kind <> akTuple then
ErrorFmt('%s expects a vector [...]', [Context]);
SetLength(Result, Length(list));
for i := 0 to High(list) do
tuple := Node.AsTuple;
SetLength(Result, tuple.Count);
for i := 0 to tuple.Count - 1 do
begin
if list[i].Kind <> akIdentifier then
if tuple.Items[i].Kind <> akIdentifier then
ErrorFmt('%s vector must contain only identifiers.', [Context]);
Result[i] := list[i].AsIdentifier;
Result[i] := tuple.Items[i].AsIdentifier;
end;
end;
@@ -499,6 +494,7 @@ begin
fields.Add(TAst.RecordField(keyNode, fieldValue, keyToken.GetLocation));
end;
// Factory automatically wraps array into TupleNode
Result := TAst.RecordLiteral(fields.ToArray, startLoc);
finally
fields.Free;
@@ -540,40 +536,40 @@ begin
if Length(tailNodes) <> 2 then
Error('Syntax Error: ''pipe'' requires [inputs] vector and (fn) transformation.');
// Input vector is now a TupleNode
if tailNodes[0].Kind <> akTuple then
Error('Syntax Error: ''pipe'' first argument must be a vector [...].');
var rawInputs := tailNodes[0].AsTuple.Elements;
if (Length(rawInputs) mod 2) <> 0 then
// Access tuple elements safely
var inputsTuple := tailNodes[0].AsTuple;
if (inputsTuple.Count mod 2) <> 0 then
Error('Syntax Error: Pipe inputs must be pairs of Identifier and Selector Vector (e.g. [btc [:Close]]).');
var pipeInputs := TList<IPipeInputNode>.Create;
try
var k := 0;
while k < Length(rawInputs) do
while k < inputsTuple.Count do
begin
if rawInputs[k].Kind <> akIdentifier then
var streamNode := inputsTuple.Items[k];
if streamNode.Kind <> akIdentifier then
Error('Syntax Error: Pipe input stream must be an identifier.');
var selNode := rawInputs[k + 1];
var streamId := rawInputs[k].AsIdentifier;
var selNode := inputsTuple.Items[k + 1];
var streamId := streamNode.AsIdentifier;
var selKeywords: TArray<IKeywordNode>;
// Strict format: Selector must be a vector [...] (TupleNode) containing keywords
if selNode.Kind <> akTuple then
Error('Syntax Error: Pipe selector must be a vector of keywords (e.g. [:Close :High]).');
var selList := selNode.AsTuple.Elements;
if Length(selList) = 0 then
var selTuple := selNode.AsTuple;
if selTuple.Count = 0 then
Error('Syntax Error: Selector list cannot be empty.');
SetLength(selKeywords, Length(selList));
for var m := 0 to High(selList) do
SetLength(selKeywords, selTuple.Count);
for var m := 0 to selTuple.Count - 1 do
begin
if selList[m].Kind <> akKeyword then
if selTuple.Items[m].Kind <> akKeyword then
Error('Syntax Error: Selector vector must contain only keywords.');
selKeywords[m] := selList[m].AsKeyword;
selKeywords[m] := selTuple.Items[m].AsKeyword;
end;
var selectorList := TAst.PipeSelectorList(selKeywords, selNode.Identity.Location);
@@ -638,10 +634,12 @@ begin
end
else if SameText(head.Token.Text, 'do') then
begin
// Factory takes Array and creates Tuple
Result := TAst.Block(tailNodes, startLoc)
end
else if SameText(head.Token.Text, 'recur') then
begin
// Factory takes Array and creates Tuple
Result := TAst.Recur(tailNodes, startLoc)
end
else if SameText(head.Token.Text, 'get') then
@@ -675,6 +673,7 @@ begin
end;
if Result = nil then
// Factory automatically creates Tuple from Array for Arguments
Result := TAst.FunctionCall(head.Node, tailNodes, startLoc);
finally