Ast list nodes

This commit is contained in:
Michael Schimmel
2025-11-29 18:59:16 +01:00
parent 250f950a68
commit 851f56c63f
24 changed files with 1819 additions and 863 deletions
+78 -34
View File
@@ -44,7 +44,7 @@ type
function JsonToVarDeclNode(const AObj: TJSONObject): IVariableDeclarationNode;
function JsonToAssignmentNode(const AObj: TJSONObject): IAssignmentNode;
function JsonToIndexerNode(const AObj: TJSONObject): IIndexerNode;
function JsonToMemberAccessNode(const AObj: TJSONObject): IMemberAccessNode;
function JsonToMemberAccessNode(const AObj: TJSONObject): IMemberAccessNode; // <--- KORRIGIERT
function JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
function JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
@@ -56,6 +56,14 @@ type
function VisitConstant(const Node: IConstantNode): TJSONObject; override;
function VisitIdentifier(const Node: IIdentifierNode): TJSONObject; override;
function VisitKeyword(const Node: IKeywordNode): TJSONObject; override;
// List Visitors (stubbed mostly, as parents handle array generation for JSON structure)
function VisitParameterList(const Node: IParameterList): TJSONObject; override;
function VisitArgumentList(const Node: IArgumentList): TJSONObject; override;
function VisitExpressionList(const Node: IExpressionList): TJSONObject; override;
function VisitRecordFieldList(const Node: IRecordFieldList): TJSONObject; override;
function VisitRecordField(const Node: IRecordFieldNode): TJSONObject; override;
function VisitIfExpression(const Node: IIfExpressionNode): TJSONObject; override;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TJSONObject; override;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject; override;
@@ -197,12 +205,13 @@ function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNo
var
bodyObj: TJSONObject;
paramsArray: TJSONArray;
i: Integer;
begin
bodyObj := Accept(Node.Body);
paramsArray := TJSONArray.Create;
for var param in Node.Parameters do
paramsArray.Add(Accept(param));
for i := 0 to Node.Parameters.Count - 1 do
paramsArray.Add(Accept(Node.Parameters[i]));
Result := TJSONObject.Create;
Result.AddPair('NodeType', TJSONString.Create('LambdaExpr'));
@@ -214,13 +223,14 @@ function TJsonAstConverter.VisitMacroDefinition(const Node: IMacroDefinitionNode
var
nameObj, bodyObj: TJSONObject;
paramsArray: TJSONArray;
i: Integer;
begin
nameObj := Accept(Node.Name);
bodyObj := Accept(Node.Body);
paramsArray := TJSONArray.Create;
for var param in Node.Parameters do
paramsArray.Add(Accept(param));
for i := 0 to Node.Parameters.Count - 1 do
paramsArray.Add(Accept(Node.Parameters[i]));
Result := TJSONObject.Create;
Result.AddPair('NodeType', TJSONString.Create('MacroDef'));
@@ -254,13 +264,13 @@ function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TJS
var
calleeObj: TJSONObject;
argsArray: TJSONArray;
arg: IAstNode;
i: Integer;
begin
calleeObj := Accept(Node.Callee);
argsArray := TJSONArray.Create;
for arg in Node.Arguments do
argsArray.Add(Accept(arg));
for i := 0 to Node.Arguments.Count - 1 do
argsArray.Add(Accept(Node.Arguments[i]));
Result := TJSONObject.Create;
Result.AddPair('NodeType', TJSONString.Create('FunctionCall'));
@@ -272,14 +282,14 @@ function TJsonAstConverter.VisitMacroExpansionNode(const Node: IMacroExpansionNo
var
calleeObj, bodyObj: TJSONObject;
argsArray: TJSONArray;
arg: IAstNode;
i: Integer;
begin
calleeObj := Accept(Node.CallNode.Callee);
bodyObj := Accept(Node.ExpandedBody);
argsArray := TJSONArray.Create;
for arg in Node.CallNode.Arguments do
argsArray.Add(Accept(arg));
for i := 0 to Node.CallNode.Arguments.Count - 1 do
argsArray.Add(Accept(Node.CallNode.Arguments[i]));
Result := TJSONObject.Create;
Result.AddPair('NodeType', TJSONString.Create('MacroExpansion'));
@@ -291,11 +301,11 @@ end;
function TJsonAstConverter.VisitRecurNode(const Node: IRecurNode): TJSONObject;
var
argsArray: TJSONArray;
arg: IAstNode;
i: Integer;
begin
argsArray := TJSONArray.Create;
for arg in Node.Arguments do
argsArray.Add(Accept(arg));
for i := 0 to Node.Arguments.Count - 1 do
argsArray.Add(Accept(Node.Arguments[i]));
Result := TJSONObject.Create;
Result.AddPair('NodeType', TJSONString.Create('Recur'));
@@ -305,11 +315,11 @@ end;
function TJsonAstConverter.VisitBlockExpression(const Node: IBlockExpressionNode): TJSONObject;
var
exprsArray: TJSONArray;
expr: IAstNode;
i: Integer;
begin
exprsArray := TJSONArray.Create;
for expr in Node.Expressions do
exprsArray.Add(Accept(expr));
for i := 0 to Node.Expressions.Count - 1 do
exprsArray.Add(Accept(Node.Expressions[i]));
Result := TJSONObject.Create;
Result.AddPair('NodeType', TJSONString.Create('Block'));
@@ -375,24 +385,28 @@ end;
function TJsonAstConverter.VisitRecordLiteral(const Node: IRecordLiteralNode): TJSONObject;
var
fieldsArray: TJSONArray;
field: TRecordFieldLiteral;
fieldObj: TJSONObject;
i: Integer;
begin
Result := TJSONObject.Create;
Result.AddPair('NodeType', TJSONString.Create('RecordLiteral'));
fieldsArray := TJSONArray.Create;
for field in Node.Fields do
for i := 0 to Node.Fields.Count - 1 do
begin
fieldObj := TJSONObject.Create;
fieldObj.AddPair('Name', TJSONString.Create(field.Key.Value.Name));
fieldObj.AddPair('Value', Accept(field.Value)); // Get TJSONObject
fieldsArray.Add(fieldObj);
// We visit the RecordFieldNode, which returns a JSON Object
fieldsArray.Add(Accept(Node.Fields[i]));
end;
Result.AddPair('Fields', fieldsArray);
end;
function TJsonAstConverter.VisitRecordField(const Node: IRecordFieldNode): TJSONObject;
begin
Result := TJSONObject.Create;
Result.AddPair('Name', TJSONString.Create(Node.Key.Value.Name));
Result.AddPair('Value', Accept(Node.Value));
end;
function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TJSONObject;
begin
Result := TJSONObject.Create;
@@ -436,7 +450,35 @@ begin
Result.AddPair('NodeType', TJSONString.Create('Nop'));
end;
{ TJsonAstConverter - Deserialization }
// --- List Visitors (Placeholder return) ---
// Since we iterate manually in parent nodes to form JSON Arrays, these are technically not used
// by the current logic, but required by the interface.
// Note: If we wanted strict visitor compliance, VisitFunctionCall would call Accept(List),
// which would return TJSONObject wrapping the array. We skip that level of nesting here.
function TJsonAstConverter.VisitParameterList(const Node: IParameterList): TJSONObject;
begin
Result := nil;
end;
function TJsonAstConverter.VisitArgumentList(const Node: IArgumentList): TJSONObject;
begin
Result := nil;
end;
function TJsonAstConverter.VisitExpressionList(const Node: IExpressionList): TJSONObject;
begin
Result := nil;
end;
function TJsonAstConverter.VisitRecordFieldList(const Node: IRecordFieldList): TJSONObject;
begin
Result := nil;
end;
// ------------------------------------------------------------------------------------------------
// Deserialization
// ------------------------------------------------------------------------------------------------
function TJsonAstConverter.JsonToDataValue(const AObj: TJSONObject; const AName: string): TDataValue;
var
@@ -532,11 +574,10 @@ function TJsonAstConverter.JsonToMacroDefNode(const AObj: TJSONObject): IMacroDe
var
name: IIdentifierNode;
params: TArray<IIdentifierNode>;
body: IQuasiquoteNode;
body: IAstNode;
paramArray: TJSONArray;
i: Integer;
begin
name := JsonToIdentifierNode(AObj.GetValue('Name') as TJSONObject);
paramArray := AObj.GetValue<TJSONArray>('Parameters');
@@ -544,7 +585,7 @@ begin
for i := 0 to paramArray.Count - 1 do
params[i] := JsonToIdentifierNode(paramArray.Items[i] as TJSONObject);
body := IQuasiquoteNode(JsonToNode(AObj.GetValue('Body'), 'Quasiquote'));
body := JsonToNode(AObj.GetValue('Body'), 'Quasiquote');
Result := TAst.MacroDef(name, params, body);
end;
@@ -556,7 +597,6 @@ var
i: Integer;
tempCallNode: IFunctionCallNode;
begin
// Recursively deserialize all parts of the macro expansion node
callee := JsonToNode(AObj.GetValue('Callee'));
expandedBody := JsonToNode(AObj.GetValue('ExpandedBody'));
argsArray := AObj.GetValue<TJSONArray>('Arguments');
@@ -564,10 +604,7 @@ begin
for i := 0 to argsArray.Count - 1 do
args[i] := JsonToNode(argsArray.Items[i]);
// Create a temporary IFunctionCallNode to pass to the factory
tempCallNode := TAst.FunctionCall(callee, args);
// Use the new global factory function from the TAst record
Result := TAst.MacroExpansionNode(tempCallNode, expandedBody);
end;
@@ -666,18 +703,25 @@ end;
function TJsonAstConverter.JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
var
fields: TArray<TRecordFieldLiteral>;
fields: TArray<IRecordFieldNode>;
fieldsArray: TJSONArray;
fieldObj: TJSONObject;
i: Integer;
keyNode: IKeywordNode;
valueNode: IAstNode;
begin
fieldsArray := AObj.GetValue<TJSONArray>('Fields');
SetLength(fields, fieldsArray.Count);
for i := 0 to fieldsArray.Count - 1 do
begin
fieldObj := fieldsArray.Items[i] as TJSONObject;
fields[i] := TRecordFieldLiteral.Create(TAst.Keyword(fieldObj.GetValue<string>('Name')), JsonToNode(fieldObj.GetValue('Value')));
keyNode := TAst.Keyword(fieldObj.GetValue<string>('Name'));
valueNode := JsonToNode(fieldObj.GetValue('Value'));
fields[i] := TAst.RecordField(keyNode, valueNode);
end;
Result := TAst.RecordLiteral(fields);
end;