Json Schema for LLMs
This commit is contained in:
+292
-249
@@ -1,14 +1,11 @@
|
||||
//==================================================================================================
|
||||
//== FULL UNIT START: Myc.Ast.Json (from Myc.Ast.Json.pas)
|
||||
//==================================================================================================
|
||||
unit Myc.Ast.Json;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.Generics.Collections,
|
||||
System.JSON,
|
||||
system.sysutils,
|
||||
system.generics.collections,
|
||||
system.json,
|
||||
Myc.Data.Scalar,
|
||||
Myc.Data.Value,
|
||||
Myc.Ast,
|
||||
@@ -21,19 +18,16 @@ type
|
||||
function Deserialize(const AJson: TJSONValue): IAstNode;
|
||||
end;
|
||||
|
||||
// Compact JSON Converter: [Kind, Arg1, Arg2, ...]
|
||||
{ Compact JSON Converter: [Tag, Arg1, Arg2, ...] }
|
||||
TJsonAstConverter = class(TAstVisitor<TJSONValue>, IJsonAstConverter)
|
||||
private
|
||||
// Helpers for compact data values
|
||||
function DataValueToJson(const AValue: TDataValue): TJSONValue;
|
||||
function JsonToDataValue(const AJson: TJSONValue): TDataValue;
|
||||
|
||||
// Deserialization Dispatcher
|
||||
function JsonToNode(const AJson: TJSONValue): IAstNode;
|
||||
function JsonToTuple(const AArray: TJSONArray): ITupleNode;
|
||||
|
||||
strict private
|
||||
// Serialization Visitors (Array Builders)
|
||||
function VisitConstant(const Node: IAstNode): TJSONValue;
|
||||
function VisitIdentifier(const Node: IAstNode): TJSONValue;
|
||||
function VisitKeyword(const Node: IAstNode): TJSONValue;
|
||||
@@ -42,16 +36,16 @@ type
|
||||
function VisitIfExpression(const Node: IAstNode): TJSONValue;
|
||||
function VisitCondExpression(const Node: IAstNode): TJSONValue;
|
||||
function VisitLambdaExpression(const Node: IAstNode): TJSONValue;
|
||||
function VisitMacroDefinition(const Node: IAstNode): TJSONValue;
|
||||
function VisitQuasiquote(const Node: IAstNode): TJSONValue;
|
||||
function VisitUnquote(const Node: IAstNode): TJSONValue;
|
||||
function VisitUnquoteSplicing(const Node: IAstNode): TJSONValue;
|
||||
function VisitFunctionCall(const Node: IAstNode): TJSONValue;
|
||||
function VisitMacroExpansionNode(const Node: IAstNode): TJSONValue;
|
||||
function VisitRecurNode(const Node: IAstNode): TJSONValue;
|
||||
function VisitBlockExpression(const Node: IAstNode): TJSONValue;
|
||||
function VisitVariableDeclaration(const Node: IAstNode): TJSONValue;
|
||||
function VisitAssignment(const Node: IAstNode): TJSONValue;
|
||||
function VisitMacroDefinition(const Node: IAstNode): TJSONValue;
|
||||
function VisitQuasiquote(const Node: IAstNode): TJSONValue;
|
||||
function VisitUnquote(const Node: IAstNode): TJSONValue;
|
||||
function VisitUnquoteSplicing(const Node: IAstNode): TJSONValue;
|
||||
function VisitIndexer(const Node: IAstNode): TJSONValue;
|
||||
function VisitMemberAccess(const Node: IAstNode): TJSONValue;
|
||||
function VisitRecordLiteral(const Node: IAstNode): TJSONValue;
|
||||
@@ -125,31 +119,7 @@ begin
|
||||
Result := JsonToNode(AJson);
|
||||
end;
|
||||
|
||||
// --- Serialization (AST -> JSON Array) ---
|
||||
|
||||
function TJsonAstConverter.VisitIdentifier(const Node: IAstNode): TJSONValue;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Id'));
|
||||
arr.AddElement(TJSONString.Create(Node.AsIdentifier.Name));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitKeyword(const Node: IAstNode): TJSONValue;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Key'));
|
||||
arr.AddElement(TJSONString.Create(Node.AsKeyword.Value.Name));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitConstant(const Node: IAstNode): TJSONValue;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Const'));
|
||||
arr.AddElement(DataValueToJson(Node.AsConstant.Value));
|
||||
Result := arr;
|
||||
end;
|
||||
// --- Serialization Helpers ---
|
||||
|
||||
function TJsonAstConverter.DataValueToJson(const AValue: TDataValue): TJSONValue;
|
||||
begin
|
||||
@@ -177,97 +147,74 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitTuple(const Node: IAstNode): TJSONValue;
|
||||
// --- Visitor Implementations ---
|
||||
|
||||
function TJsonAstConverter.VisitConstant(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Tuple'));
|
||||
var elems := TJSONArray.Create;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Const');
|
||||
arr.AddElement(DataValueToJson(Node.AsConstant.Value));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitIdentifier(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Id');
|
||||
arr.Add(Node.AsIdentifier.Name);
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitKeyword(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Key');
|
||||
arr.Add(Node.AsKeyword.Value.Name);
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitTuple(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr, elems: TJSONArray;
|
||||
begin
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Tuple');
|
||||
elems := TJSONArray.Create;
|
||||
for var item in Node.AsTuple.Elements do
|
||||
elems.AddElement(Visit(item));
|
||||
arr.AddElement(elems);
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitFunctionCall(const Node: IAstNode): TJSONValue;
|
||||
function TJsonAstConverter.VisitRecordField(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
C: IFunctionCallNode;
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
C := Node.AsFunctionCall;
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Call'));
|
||||
arr.AddElement(Visit(C.Callee));
|
||||
arr.AddElement(Visit(C.Arguments)); // Arguments is a Tuple
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitBlockExpression(const Node: IAstNode): TJSONValue;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Block'));
|
||||
arr.AddElement(Visit(Node.AsBlockExpression.Expressions)); // Tuple
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitLambdaExpression(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
L: ILambdaExpressionNode;
|
||||
begin
|
||||
L := Node.AsLambdaExpression;
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Fn'));
|
||||
arr.AddElement(Visit(L.Parameters)); // Tuple
|
||||
arr.AddElement(Visit(L.Body));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitMacroDefinition(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
M: IMacroDefinitionNode;
|
||||
begin
|
||||
M := Node.AsMacroDefinition;
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Macro'));
|
||||
arr.AddElement(Visit(M.Name));
|
||||
arr.AddElement(Visit(M.Parameters));
|
||||
arr.AddElement(Visit(M.Body));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitVariableDeclaration(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
V: IVariableDeclarationNode;
|
||||
begin
|
||||
V := Node.AsVariableDeclaration;
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Var'));
|
||||
arr.AddElement(Visit(V.Target));
|
||||
if Assigned(V.Initializer) then
|
||||
arr.AddElement(Visit(V.Initializer))
|
||||
else
|
||||
arr.AddElement(TJSONNull.Create);
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitAssignment(const Node: IAstNode): TJSONValue;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Assign'));
|
||||
arr.AddElement(Visit(Node.AsAssignment.Target));
|
||||
arr.AddElement(Visit(Node.AsAssignment.Value));
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Field');
|
||||
arr.AddElement(Visit(Node.AsRecordField.Key));
|
||||
arr.AddElement(Visit(Node.AsRecordField.Value));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitIfExpression(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
E: IIfExpressionNode;
|
||||
arr: TJSONArray;
|
||||
n: IIfExpressionNode;
|
||||
begin
|
||||
E := Node.AsIfExpression;
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('If'));
|
||||
arr.AddElement(Visit(E.Condition));
|
||||
arr.AddElement(Visit(E.ThenBranch));
|
||||
if Assigned(E.ElseBranch) then
|
||||
arr.AddElement(Visit(E.ElseBranch))
|
||||
n := Node.AsIfExpression;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('If');
|
||||
arr.AddElement(Visit(n.Condition));
|
||||
arr.AddElement(Visit(n.ThenBranch));
|
||||
if Assigned(n.ElseBranch) then
|
||||
arr.AddElement(Visit(n.ElseBranch))
|
||||
else
|
||||
arr.AddElement(TJSONNull.Create);
|
||||
Result := arr;
|
||||
@@ -275,147 +222,248 @@ end;
|
||||
|
||||
function TJsonAstConverter.VisitCondExpression(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
E: ICondExpressionNode;
|
||||
pairs: TJSONArray;
|
||||
arr, pairs: TJSONArray;
|
||||
n: ICondExpressionNode;
|
||||
begin
|
||||
E := Node.AsCondExpression;
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Cond'));
|
||||
n := Node.AsCondExpression;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Cond');
|
||||
pairs := TJSONArray.Create;
|
||||
for var p in E.Pairs do
|
||||
for var p in n.Pairs do
|
||||
begin
|
||||
var pArr := TJSONArray.Create;
|
||||
pArr.AddElement(Visit(p.Condition));
|
||||
pArr.AddElement(Visit(p.Branch));
|
||||
pairs.AddElement(pArr);
|
||||
var pairArr := TJSONArray.Create;
|
||||
pairArr.AddElement(Visit(p.Condition));
|
||||
pairArr.AddElement(Visit(p.Branch));
|
||||
pairs.AddElement(pairArr);
|
||||
end;
|
||||
arr.AddElement(pairs);
|
||||
if Assigned(E.ElseBranch) then
|
||||
arr.AddElement(Visit(E.ElseBranch))
|
||||
if Assigned(n.ElseBranch) then
|
||||
arr.AddElement(Visit(n.ElseBranch))
|
||||
else
|
||||
arr.AddElement(TJSONNull.Create);
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitQuasiquote(const Node: IAstNode): TJSONValue;
|
||||
function TJsonAstConverter.VisitLambdaExpression(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
n: ILambdaExpressionNode;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Quote'));
|
||||
n := Node.AsLambdaExpression;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Fn');
|
||||
arr.AddElement(Visit(n.Parameters));
|
||||
arr.AddElement(Visit(n.Body));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitFunctionCall(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
n: IFunctionCallNode;
|
||||
begin
|
||||
n := Node.AsFunctionCall;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Call');
|
||||
arr.AddElement(Visit(n.Callee));
|
||||
arr.AddElement(Visit(n.Arguments));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitMacroExpansionNode(const Node: IAstNode): TJSONValue;
|
||||
begin
|
||||
Result := Visit(Node.AsMacroExpansion.CallNode);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitBlockExpression(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Block');
|
||||
arr.AddElement(Visit(Node.AsBlockExpression.Expressions));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitVariableDeclaration(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
n: IVariableDeclarationNode;
|
||||
begin
|
||||
n := Node.AsVariableDeclaration;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Var');
|
||||
arr.AddElement(Visit(n.Target));
|
||||
if Assigned(n.Initializer) then
|
||||
arr.AddElement(Visit(n.Initializer))
|
||||
else
|
||||
arr.AddElement(TJSONNull.Create);
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitAssignment(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
n: IAssignmentNode;
|
||||
begin
|
||||
n := Node.AsAssignment;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Assign');
|
||||
arr.AddElement(Visit(n.Target));
|
||||
arr.AddElement(Visit(n.Value));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitMacroDefinition(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
n: IMacroDefinitionNode;
|
||||
begin
|
||||
n := Node.AsMacroDefinition;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Macro');
|
||||
arr.AddElement(Visit(n.Name));
|
||||
arr.AddElement(Visit(n.Parameters));
|
||||
arr.AddElement(Visit(n.Body));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitQuasiquote(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Quote');
|
||||
arr.AddElement(Visit(Node.AsQuasiquote.Expression));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitUnquote(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Unquote'));
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Unquote');
|
||||
arr.AddElement(Visit(Node.AsUnquote.Expression));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitUnquoteSplicing(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Splice'));
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Splice');
|
||||
arr.AddElement(Visit(Node.AsUnquoteSplicing.Expression));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitRecurNode(const Node: IAstNode): TJSONValue;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Recur'));
|
||||
arr.AddElement(Visit(Node.AsRecur.Arguments)); // Tuple
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitIndexer(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
n: IIndexerNode;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Index'));
|
||||
arr.AddElement(Visit(Node.AsIndexer.Base));
|
||||
arr.AddElement(Visit(Node.AsIndexer.Index));
|
||||
n := Node.AsIndexer;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Index');
|
||||
arr.AddElement(Visit(n.Base));
|
||||
arr.AddElement(Visit(n.Index));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitMemberAccess(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
n: IMemberAccessNode;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Member'));
|
||||
arr.AddElement(Visit(Node.AsMemberAccess.Base));
|
||||
arr.AddElement(Visit(Node.AsMemberAccess.Member));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitRecordField(const Node: IAstNode): TJSONValue;
|
||||
begin
|
||||
// Helper for RecordLiteral
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Field'));
|
||||
arr.AddElement(Visit(Node.AsRecordField.Key));
|
||||
arr.AddElement(Visit(Node.AsRecordField.Value));
|
||||
n := Node.AsMemberAccess;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Member');
|
||||
arr.AddElement(Visit(n.Base));
|
||||
arr.AddElement(Visit(n.Member));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitRecordLiteral(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Record'));
|
||||
arr.AddElement(Visit(Node.AsRecordLiteral.Fields)); // Tuple
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Record');
|
||||
arr.AddElement(Visit(Node.AsRecordLiteral.Fields));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitCreateSeries(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Series'));
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Series');
|
||||
arr.AddElement(Visit(Node.AsCreateSeries.DefinitionNode));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitAddSeriesItem(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
n: IAddSeriesItemNode;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Add'));
|
||||
arr.AddElement(Visit(Node.AsAddSeriesItem.Series));
|
||||
arr.AddElement(Visit(Node.AsAddSeriesItem.Value));
|
||||
if Assigned(Node.AsAddSeriesItem.Lookback) then
|
||||
arr.AddElement(Visit(Node.AsAddSeriesItem.Lookback))
|
||||
n := Node.AsAddSeriesItem;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Add');
|
||||
arr.AddElement(Visit(n.Series));
|
||||
arr.AddElement(Visit(n.Value));
|
||||
if Assigned(n.Lookback) then
|
||||
arr.AddElement(Visit(n.Lookback))
|
||||
else
|
||||
arr.AddElement(TJSONNull.Create);
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitSeriesLength(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Count'));
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Count');
|
||||
arr.AddElement(Visit(Node.AsSeriesLength.Series));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitPipe(const Node: IAstNode): TJSONValue;
|
||||
function TJsonAstConverter.VisitRecurNode(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
var arr := TJSONArray.Create;
|
||||
arr.AddElement(TJSONString.Create('Pipe'));
|
||||
arr.AddElement(Visit(Node.AsPipe.Inputs));
|
||||
arr.AddElement(Visit(Node.AsPipe.Transformation));
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Recur');
|
||||
arr.AddElement(Visit(Node.AsRecur.Arguments));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitNop(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
begin
|
||||
Result := TJSONArray.Create;
|
||||
TJSONArray(Result).AddElement(TJSONString.Create('Nop'));
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Nop');
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitMacroExpansionNode(const Node: IAstNode): TJSONValue;
|
||||
function TJsonAstConverter.VisitPipe(const Node: IAstNode): TJSONValue;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
n: IPipeNode;
|
||||
begin
|
||||
// Serialize original call
|
||||
Result := Visit(Node.AsMacroExpansion.CallNode);
|
||||
n := Node.AsPipe;
|
||||
arr := TJSONArray.Create;
|
||||
arr.Add('Pipe');
|
||||
arr.AddElement(Visit(n.Inputs));
|
||||
arr.AddElement(Visit(n.Transformation));
|
||||
Result := arr;
|
||||
end;
|
||||
|
||||
// --- Deserialization (JSON Array -> AST) ---
|
||||
// --- Deserialization ---
|
||||
|
||||
function TJsonAstConverter.JsonToDataValue(const AJson: TJSONValue): TDataValue;
|
||||
var
|
||||
@@ -458,8 +506,18 @@ function TJsonAstConverter.JsonToNode(const AJson: TJSONValue): IAstNode;
|
||||
var
|
||||
arr: TJSONArray;
|
||||
kind: string;
|
||||
|
||||
function UnpackTuple(Val: TJSONValue): TArray<IAstNode>;
|
||||
begin
|
||||
var n := JsonToNode(Val);
|
||||
if Assigned(n) then
|
||||
Result := n.AsTuple.Elements
|
||||
else
|
||||
Result := [];
|
||||
end;
|
||||
|
||||
begin
|
||||
if AJson is TJSONNull then
|
||||
if (not Assigned(AJson)) or (AJson is TJSONNull) then
|
||||
exit(nil);
|
||||
|
||||
if not (AJson is TJSONArray) then
|
||||
@@ -472,32 +530,45 @@ begin
|
||||
kind := arr.Items[0].Value;
|
||||
|
||||
if kind = 'Id' then
|
||||
Exit(TAst.Identifier(arr.Items[1].Value));
|
||||
exit(TAst.Identifier(arr.Items[1].Value));
|
||||
if kind = 'Key' then
|
||||
Exit(TAst.Keyword(arr.Items[1].Value));
|
||||
exit(TAst.Keyword(arr.Items[1].Value));
|
||||
if kind = 'Const' then
|
||||
Exit(TAst.Constant(JsonToDataValue(arr.Items[1])));
|
||||
if kind = 'Tuple' then
|
||||
Exit(JsonToTuple(arr.Items[1] as TJSONArray));
|
||||
if kind = 'Block' then
|
||||
Exit(TAst.Block(JsonToTuple(arr.Items[1] as TJSONArray).Elements));
|
||||
exit(TAst.Constant(JsonToDataValue(arr.Items[1])));
|
||||
if kind = 'Nop' then
|
||||
Exit(TAst.Nop);
|
||||
exit(TAst.Nop);
|
||||
|
||||
if kind = 'Tuple' then
|
||||
exit(JsonToTuple(arr.Items[1] as TJSONArray));
|
||||
if kind = 'Block' then
|
||||
exit(TAst.Block(UnpackTuple(arr.Items[1])));
|
||||
if kind = 'Record' then
|
||||
begin
|
||||
var fields := UnpackTuple(arr.Items[1]);
|
||||
var recFields := TList<IRecordFieldNode>.Create;
|
||||
try
|
||||
for var f in fields do
|
||||
recFields.Add(f.AsRecordField);
|
||||
exit(TAst.RecordLiteral(recFields.ToArray));
|
||||
finally
|
||||
recFields.Free;
|
||||
end;
|
||||
end;
|
||||
if kind = 'Field' then
|
||||
exit(TAst.RecordField(JsonToNode(arr.Items[1]).AsKeyword, JsonToNode(arr.Items[2])));
|
||||
if kind = 'Call' then
|
||||
Exit(TAst.FunctionCall(JsonToNode(arr.Items[1]), JsonToTuple(arr.Items[2] as TJSONArray).Elements));
|
||||
|
||||
exit(TAst.FunctionCall(JsonToNode(arr.Items[1]), UnpackTuple(arr.Items[2])));
|
||||
if kind = 'Fn' then
|
||||
// Pass TIdentities.Structural as Identity to satisfy the overload requiring (Identity, Tuple, Body, ...)
|
||||
Exit(TAst.LambdaExpr(TIdentities.Structural, JsonToTuple(arr.Items[1] as TJSONArray), JsonToNode(arr.Items[2])));
|
||||
exit(TAst.LambdaExpr(TIdentities.Structural, JsonToNode(arr.Items[1]).AsTuple, JsonToNode(arr.Items[2])));
|
||||
if kind = 'Recur' then
|
||||
exit(TAst.Recur(UnpackTuple(arr.Items[1])));
|
||||
|
||||
if kind = 'Macro' then
|
||||
// Pass TIdentities.Structural as Identity
|
||||
Exit(
|
||||
exit(
|
||||
TAst.MacroDef(
|
||||
TIdentities.Structural,
|
||||
JsonToNode(arr.Items[1]).AsIdentifier,
|
||||
JsonToTuple(arr.Items[2] as TJSONArray),
|
||||
JsonToNode(arr.Items[2]).AsTuple,
|
||||
JsonToNode(arr.Items[3])
|
||||
)
|
||||
);
|
||||
@@ -505,20 +576,20 @@ begin
|
||||
if kind = 'Var' then
|
||||
begin
|
||||
var init: IAstNode := nil;
|
||||
if arr.Count > 2 then
|
||||
if (arr.Count > 2) and (not (arr.Items[2] is TJSONNull)) then
|
||||
init := JsonToNode(arr.Items[2]);
|
||||
Exit(TAst.VarDecl(JsonToNode(arr.Items[1]), init));
|
||||
exit(TAst.VarDecl(JsonToNode(arr.Items[1]), init));
|
||||
end;
|
||||
|
||||
if kind = 'Assign' then
|
||||
Exit(TAst.Assign(JsonToNode(arr.Items[1]), JsonToNode(arr.Items[2])));
|
||||
exit(TAst.Assign(JsonToNode(arr.Items[1]), JsonToNode(arr.Items[2])));
|
||||
|
||||
if kind = 'If' then
|
||||
begin
|
||||
var el: IAstNode := nil;
|
||||
if arr.Count > 3 then
|
||||
if (arr.Count > 3) and (not (arr.Items[3] is TJSONNull)) then
|
||||
el := JsonToNode(arr.Items[3]);
|
||||
Exit(TAst.IfExpr(JsonToNode(arr.Items[1]), JsonToNode(arr.Items[2]), el));
|
||||
exit(TAst.IfExpr(JsonToNode(arr.Items[1]), JsonToNode(arr.Items[2]), el));
|
||||
end;
|
||||
|
||||
if kind = 'Cond' then
|
||||
@@ -532,68 +603,40 @@ begin
|
||||
pairs[i] := TCondPair.Create(JsonToNode(p.Items[0]), JsonToNode(p.Items[1]));
|
||||
end;
|
||||
var el: IAstNode := nil;
|
||||
if arr.Count > 2 then
|
||||
if (arr.Count > 2) and (not (arr.Items[2] is TJSONNull)) then
|
||||
el := JsonToNode(arr.Items[2]);
|
||||
Exit(TAst.CondExpr(pairs, el));
|
||||
exit(TAst.CondExpr(pairs, el));
|
||||
end;
|
||||
|
||||
if kind = 'Quote' then
|
||||
Exit(TAst.Quasiquote(JsonToNode(arr.Items[1])));
|
||||
exit(TAst.Quasiquote(JsonToNode(arr.Items[1])));
|
||||
if kind = 'Unquote' then
|
||||
Exit(TAst.Unquote(JsonToNode(arr.Items[1])));
|
||||
exit(TAst.Unquote(JsonToNode(arr.Items[1])));
|
||||
|
||||
// Splice Fix: Direkte Instanziierung um Factory-Overload E2250 zu umgehen
|
||||
if kind = 'Splice' then
|
||||
Exit(TAst.UnquoteSplicing(JsonToNode(arr.Items[1]).AsQuasiquote));
|
||||
if kind = 'Recur' then
|
||||
Exit(TAst.Recur(JsonToTuple(arr.Items[1] as TJSONArray).Elements));
|
||||
exit(TUnquoteSplicingNode.Create(JsonToNode(arr.Items[1]), TIdentities.Structural(nil)));
|
||||
|
||||
if kind = 'Index' then
|
||||
Exit(TAst.Indexer(JsonToNode(arr.Items[1]), JsonToNode(arr.Items[2])));
|
||||
exit(TAst.Indexer(JsonToNode(arr.Items[1]), JsonToNode(arr.Items[2])));
|
||||
if kind = 'Member' then
|
||||
Exit(TAst.MemberAccess(JsonToNode(arr.Items[1]), JsonToNode(arr.Items[2]).AsKeyword));
|
||||
|
||||
if kind = 'Record' then
|
||||
begin
|
||||
var fieldsTuple := JsonToTuple(arr.Items[1] as TJSONArray);
|
||||
var recFields: TList<IRecordFieldNode> := TList<IRecordFieldNode>.Create;
|
||||
try
|
||||
for var elem in fieldsTuple.Elements do
|
||||
begin
|
||||
if elem.Kind = akRecordField then
|
||||
recFields.Add(elem.AsRecordField)
|
||||
else
|
||||
raise EInvalidCast.Create('Expected RecordField');
|
||||
end;
|
||||
Exit(TAst.RecordLiteral(recFields.ToArray));
|
||||
finally
|
||||
recFields.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Explicit RecordField deserializer support
|
||||
if kind = 'Field' then
|
||||
Exit(TAst.RecordField(JsonToNode(arr.Items[1]).AsKeyword, JsonToNode(arr.Items[2])));
|
||||
|
||||
exit(TAst.MemberAccess(JsonToNode(arr.Items[1]), JsonToNode(arr.Items[2]).AsKeyword));
|
||||
if kind = 'Series' then
|
||||
Exit(TAst.CreateSeries(JsonToNode(arr.Items[1])));
|
||||
exit(TAst.CreateSeries(JsonToNode(arr.Items[1])));
|
||||
if kind = 'Count' then
|
||||
exit(TAst.SeriesLength(JsonToNode(arr.Items[1]).AsIdentifier));
|
||||
if kind = 'Pipe' then
|
||||
exit(TAst.Pipe(JsonToNode(arr.Items[1]).AsTuple, JsonToNode(arr.Items[2]).AsLambdaExpression));
|
||||
|
||||
if kind = 'Add' then
|
||||
begin
|
||||
var lb: IAstNode := nil;
|
||||
if arr.Count > 3 then
|
||||
if (arr.Count > 3) and (not (arr.Items[3] is TJSONNull)) then
|
||||
lb := JsonToNode(arr.Items[3]);
|
||||
Exit(TAst.AddSeriesItem(JsonToNode(arr.Items[1]).AsIdentifier, JsonToNode(arr.Items[2]), lb));
|
||||
exit(TAst.AddSeriesItem(JsonToNode(arr.Items[1]).AsIdentifier, JsonToNode(arr.Items[2]), lb));
|
||||
end;
|
||||
|
||||
if kind = 'Count' then
|
||||
Exit(TAst.SeriesLength(JsonToNode(arr.Items[1]).AsIdentifier));
|
||||
|
||||
if kind = 'Pipe' then
|
||||
Exit(TAst.Pipe(JsonToTuple(arr.Items[1] as TJSONArray), JsonToNode(arr.Items[2]).AsLambdaExpression));
|
||||
|
||||
raise ENotSupportedException.Create('Unknown JSON AST Kind: ' + kind);
|
||||
end;
|
||||
|
||||
end.
|
||||
//==================================================================================================
|
||||
//== FULL UNIT END: Myc.Ast.Json
|
||||
//==================================================================================================
|
||||
|
||||
Reference in New Issue
Block a user