Added user library

This commit is contained in:
Michael Schimmel
2025-09-24 10:03:10 +02:00
parent 5a1919ec07
commit 624af31243
14 changed files with 585 additions and 305 deletions
+44 -99
View File
@@ -4,29 +4,23 @@ interface
uses
System.SysUtils,
System.Generics.Collections,
System.JSON,
Myc.Data.Scalar,
Myc.Data.Value,
Myc.Ast,
Myc.Ast.Visitor,
Myc.Ast.Nodes;
type
// TAstJson provides static methods for serializing and deserializing an AST to/from JSON.
TAstJson = record
public
class function Serialize(const ANode: IAstNode): string; static;
class function Deserialize(const AJson: string): IAstNode; static;
IJsonAstConverter = interface
function Serialize(const RootNode: IAstNode): TJSONObject;
function Deserialize(const AJson: TJSONObject): IAstNode;
end;
implementation
uses
System.JSON,
System.Generics.Collections,
Myc.Ast,
Myc.Data.Scalar,
Myc.Data.Value;
type
// TJsonAstConverter implements the visitor pattern for serialization
// and uses factory functions for deserialization.
TJsonAstConverter = class(TInterfacedObject, IAstVisitor)
TJsonAstConverter = class(TAstVisitor, IJsonAstConverter)
private
FJsonObjectStack: TStack<TJSONObject>;
procedure DataValueToJson(const AValue: TDataValue; const AParent: TJSONObject; const AName: string);
@@ -52,31 +46,33 @@ type
function JsonToSeriesLengthNode(const AObj: TJSONObject): ISeriesLengthNode;
protected
// IAstVisitor implementation for serialization
function VisitConstant(const Node: IConstantNode): TDataValue;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
function VisitRecurNode(const Node: IRecurNode): TDataValue;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
function VisitAssignment(const Node: IAssignmentNode): TDataValue;
function VisitIndexer(const Node: IIndexerNode): TDataValue;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
function VisitConstant(const Node: IConstantNode): TDataValue; override;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override;
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
function Serialize(const RootNode: IAstNode): TJSONObject;
function Deserialize(const AJson: TJSONObject): IAstNode;
public
constructor Create;
destructor Destroy; override;
function Execute(const RootNode: IAstNode): TDataValue;
function Serialize(const ANode: IAstNode): string;
function Deserialize(const AJson: string): IAstNode;
end;
implementation
{ TJsonAstConverter }
constructor TJsonAstConverter.Create;
@@ -91,48 +87,9 @@ begin
inherited;
end;
function TJsonAstConverter.Serialize(const ANode: IAstNode): string;
var
rootObj: TJSONObject;
function TJsonAstConverter.Deserialize(const AJson: TJSONObject): IAstNode;
begin
if not Assigned(ANode) then
exit('');
FJsonObjectStack.Clear;
ANode.Accept(Self);
if FJsonObjectStack.Count <> 1 then
raise EInvalidOpException.Create('JSON serialization stack is corrupt.');
rootObj := FJsonObjectStack.Pop;
try
Result := rootObj.Format(4);
finally
rootObj.Free;
end;
end;
function TJsonAstConverter.Deserialize(const AJson: string): IAstNode;
var
jsonValue: TJSONValue;
begin
if AJson.IsEmpty then
exit(nil);
jsonValue := TJSONObject.ParseJSONValue(AJson);
if jsonValue = nil then
raise EJSONParseException.Create('Invalid JSON format.');
try
Result := JsonToNode(jsonValue);
finally
jsonValue.Free;
end;
end;
function TJsonAstConverter.Execute(const RootNode: IAstNode): TDataValue;
begin
Result := RootNode.Accept(Self);
Result := JsonToNode(AJson);
end;
{ TJsonAstConverter - IAstVisitor for Serialization }
@@ -782,30 +739,18 @@ begin
raise ENotSupportedException.CreateFmt('Unsupported NodeType "%s" for JSON deserialization.', [nodeType]);
end;
{ TAstJson }
class function TAstJson.Deserialize(const AJson: string): IAstNode;
var
converter: TJsonAstConverter;
function TJsonAstConverter.Serialize(const RootNode: IAstNode): TJSONObject;
begin
converter := TJsonAstConverter.Create;
try
Result := converter.Deserialize(AJson);
finally
converter.Free;
end;
end;
FJsonObjectStack.Clear;
if not Assigned(RootNode) then
exit(nil);
class function TAstJson.Serialize(const ANode: IAstNode): string;
var
converter: TJsonAstConverter;
begin
converter := TJsonAstConverter.Create;
try
Result := converter.Serialize(ANode);
finally
converter.Free;
end;
RootNode.Accept(Self);
if FJsonObjectStack.Count <> 1 then
raise EInvalidOpException.Create('JSON serialization stack is corrupt.');
Result := FJsonObjectStack.Pop;
end;
end.