This commit is contained in:
Michael Schimmel
2025-10-30 18:00:58 +01:00
parent dfe1f04333
commit 798aa08f02
12 changed files with 710 additions and 27 deletions
+74
View File
@@ -29,6 +29,7 @@ type
function JsonToConstantNode(const AObj: TJSONObject): IConstantNode;
function JsonToIdentifierNode(const AObj: TJSONObject): IIdentifierNode;
function JsonToKeywordNode(const AObj: TJSONObject): IKeywordNode;
function JsonToBinaryExprNode(const AObj: TJSONObject): IBinaryExpressionNode;
function JsonToUnaryExprNode(const AObj: TJSONObject): IUnaryExpressionNode;
function JsonToIfExprNode(const AObj: TJSONObject): IIfExpressionNode;
@@ -46,6 +47,7 @@ type
function JsonToAssignmentNode(const AObj: TJSONObject): IAssignmentNode;
function JsonToIndexerNode(const AObj: TJSONObject): IIndexerNode;
function JsonToMemberAccessNode(const AObj: TJSONObject): IMemberAccessNode;
function JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
function JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
function JsonToSeriesLengthNode(const AObj: TJSONObject): ISeriesLengthNode;
@@ -53,6 +55,7 @@ type
// IAstVisitor implementation for serialization
function VisitConstant(const Node: IConstantNode): TDataValue; override;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
function VisitKeyword(const Node: IKeywordNode): TDataValue; override;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override;
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
@@ -70,6 +73,7 @@ type
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; override;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
@@ -83,6 +87,9 @@ type
implementation
uses
Myc.Data.Keyword;
{ TJsonAstConverter }
constructor TJsonAstConverter.Create;
@@ -123,6 +130,7 @@ begin
valObj.AddPair('Value', scalarObj);
end;
vkText: valObj.AddPair('Value', TJSONString.Create(AValue.AsText));
vkKeyword: valObj.AddPair('Value', TJSONString.Create(AValue.AsKeyword.Name));
vkVoid:; // No value to add
else
raise ENotSupportedException.Create('Unsupported TDataValue kind for constant serialization.');
@@ -153,6 +161,17 @@ begin
Result := TDataValue.Void;
end;
function TJsonAstConverter.VisitKeyword(const Node: IKeywordNode): TDataValue;
var
obj: TJSONObject;
begin
obj := TJSONObject.Create;
obj.AddPair('NodeType', TJSONString.Create('Keyword'));
obj.AddPair('Name', TJSONString.Create(Node.Value.Name));
FJsonObjectStack.Push(obj);
Result := TDataValue.Void;
end;
function TJsonAstConverter.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
var
obj, leftObj, rightObj: TJSONObject;
@@ -544,6 +563,31 @@ begin
Result := TDataValue.Void;
end;
function TJsonAstConverter.VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
var
obj, fieldObj: TJSONObject;
fieldsArray: TJSONArray;
field: TRecordFieldLiteral;
begin
obj := TJSONObject.Create;
obj.AddPair('NodeType', TJSONString.Create('RecordLiteral'));
fieldsArray := TJSONArray.Create;
for field in Node.Fields do
begin
field.Value.Accept(Self); // This pushes the value JSON onto the stack
fieldObj := TJSONObject.Create;
fieldObj.AddPair('Name', TJSONString.Create(field.Name));
fieldObj.AddPair('Value', FJsonObjectStack.Pop);
fieldsArray.Add(fieldObj);
end;
obj.AddPair('Fields', fieldsArray);
FJsonObjectStack.Push(obj);
Result := TDataValue.Void;
end;
function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
var
obj: TJSONObject;
@@ -622,6 +666,10 @@ begin
begin
Result := valObj.GetValue<string>('Value');
end
else if SameText(kindStr, 'Keyword') then
begin
Result := TDataValue.FromKeyword(TKeywordRegistry.Intern(valObj.GetValue<string>('Value')));
end
else if SameText(kindStr, 'Void') then
begin
Result := TDataValue.Void;
@@ -640,6 +688,11 @@ begin
Result := TAst.Identifier(AObj.GetValue<string>('Name'));
end;
function TJsonAstConverter.JsonToKeywordNode(const AObj: TJSONObject): IKeywordNode;
begin
Result := TAst.Keyword(AObj.GetValue<string>('Name'));
end;
function TJsonAstConverter.JsonToBinaryExprNode(const AObj: TJSONObject): IBinaryExpressionNode;
var
opStr: string;
@@ -850,6 +903,23 @@ begin
Result := TAst.MemberAccess(JsonToNode(AObj.GetValue('Base')), JsonToIdentifierNode(AObj.GetValue('Member') as TJSONObject));
end;
function TJsonAstConverter.JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
var
fields: TArray<TRecordFieldLiteral>;
fieldsArray: TJSONArray;
fieldObj: TJSONObject;
i: Integer;
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(fieldObj.GetValue<string>('Name'), JsonToNode(fieldObj.GetValue('Value')));
end;
Result := TAst.RecordLiteral(fields);
end;
function TJsonAstConverter.JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
begin
Result := TAst.CreateSeries(AObj.GetValue<string>('Definition'));
@@ -891,6 +961,8 @@ begin
Result := JsonToConstantNode(obj)
else if nodeType = 'Identifier' then
Result := JsonToIdentifierNode(obj)
else if nodeType = 'Keyword' then
Result := JsonToKeywordNode(obj)
else if nodeType = 'BinaryExpr' then
Result := JsonToBinaryExprNode(obj)
else if nodeType = 'UnaryExpr' then
@@ -925,6 +997,8 @@ begin
Result := JsonToIndexerNode(obj)
else if nodeType = 'MemberAccess' then
Result := JsonToMemberAccessNode(obj)
else if nodeType = 'RecordLiteral' then
Result := JsonToRecordLiteralNode(obj)
else if nodeType = 'CreateSeries' then
Result := JsonToCreateSeriesNode(obj)
else if nodeType = 'AddSeriesItem' then