AST list refactoring
This commit is contained in:
+25
-26
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user