Binder refactoring, Monster refactoring
This commit is contained in:
+213
-408
@@ -20,9 +20,9 @@ type
|
||||
|
||||
// TJsonAstConverter implements the visitor pattern for serialization
|
||||
// and uses factory functions for deserialization.
|
||||
TJsonAstConverter = class(TAstVisitor, IJsonAstConverter)
|
||||
// Inherits from the new generic visitor base class
|
||||
TJsonAstConverter = class(TAstVisitor<TJSONObject>, IJsonAstConverter)
|
||||
private
|
||||
FJsonObjectStack: TStack<TJSONObject>;
|
||||
procedure DataValueToJson(const AValue: TDataValue; const AParent: TJSONObject; const AName: string);
|
||||
function JsonToNode(const AJson: TJSONValue; const ExpectedType: String = ''): IAstNode;
|
||||
function JsonToDataValue(const AObj: TJSONObject; const AName: string): TDataValue;
|
||||
@@ -52,37 +52,36 @@ type
|
||||
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
|
||||
function JsonToSeriesLengthNode(const AObj: TJSONObject): ISeriesLengthNode;
|
||||
protected
|
||||
// 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;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
|
||||
function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; override;
|
||||
function VisitUnquote(const Node: IUnquoteNode): TDataValue; override;
|
||||
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; override;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): 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 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;
|
||||
// IAstVisitor implementation for serialization (T = TJSONObject)
|
||||
function VisitConstant(const Node: IConstantNode): TJSONObject; override;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): TJSONObject; override;
|
||||
function VisitKeyword(const Node: IKeywordNode): TJSONObject; override;
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TJSONObject; override;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TJSONObject; override;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TJSONObject; override;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TJSONObject; override;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject; override;
|
||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TJSONObject; override;
|
||||
function VisitQuasiquote(const Node: IQuasiquoteNode): TJSONObject; override;
|
||||
function VisitUnquote(const Node: IUnquoteNode): TJSONObject; override;
|
||||
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TJSONObject; override;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TJSONObject; override;
|
||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TJSONObject; override;
|
||||
function VisitRecurNode(const Node: IRecurNode): TJSONObject; override;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TJSONObject; override;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TJSONObject; override;
|
||||
function VisitAssignment(const Node: IAssignmentNode): TJSONObject; override;
|
||||
function VisitIndexer(const Node: IIndexerNode): TJSONObject; override;
|
||||
function VisitMemberAccess(const Node: IMemberAccessNode): TJSONObject; override;
|
||||
function VisitRecordLiteral(const Node: IRecordLiteralNode): TJSONObject; override;
|
||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TJSONObject; override;
|
||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TJSONObject; override;
|
||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TJSONObject; override;
|
||||
|
||||
function Serialize(const RootNode: IAstNode): TJSONObject;
|
||||
function Deserialize(const AJson: TJSONObject): IAstNode;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@@ -95,13 +94,7 @@ uses
|
||||
constructor TJsonAstConverter.Create;
|
||||
begin
|
||||
inherited;
|
||||
FJsonObjectStack := TStack<TJSONObject>.Create;
|
||||
end;
|
||||
|
||||
destructor TJsonAstConverter.Destroy;
|
||||
begin
|
||||
FJsonObjectStack.Free;
|
||||
inherited;
|
||||
// FJsonObjectStack removed
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.Deserialize(const AJson: TJSONObject): IAstNode;
|
||||
@@ -145,506 +138,322 @@ begin
|
||||
AParent.AddPair(AName, valObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitConstant(const Node: IConstantNode): TDataValue;
|
||||
var
|
||||
obj: TJSONObject;
|
||||
function TJsonAstConverter.VisitConstant(const Node: IConstantNode): TJSONObject;
|
||||
begin
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('Constant'));
|
||||
DataValueToJson(Node.Value, obj, 'Value');
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('Constant'));
|
||||
DataValueToJson(Node.Value, Result, 'Value');
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||
var
|
||||
obj: TJSONObject;
|
||||
function TJsonAstConverter.VisitIdentifier(const Node: IIdentifierNode): TJSONObject;
|
||||
begin
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('Identifier'));
|
||||
obj.AddPair('Name', TJSONString.Create(Node.Name));
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('Identifier'));
|
||||
Result.AddPair('Name', TJSONString.Create(Node.Name));
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||
var
|
||||
obj: TJSONObject;
|
||||
function TJsonAstConverter.VisitKeyword(const Node: IKeywordNode): 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;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('Keyword'));
|
||||
Result.AddPair('Name', TJSONString.Create(Node.Value.Name));
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
|
||||
function TJsonAstConverter.VisitBinaryExpression(const Node: IBinaryExpressionNode): TJSONObject;
|
||||
var
|
||||
obj, leftObj, rightObj: TJSONObject;
|
||||
leftObj, rightObj: TJSONObject;
|
||||
begin
|
||||
Node.Left.Accept(Self);
|
||||
Node.Right.Accept(Self);
|
||||
leftObj := Accept(Node.Left);
|
||||
rightObj := Accept(Node.Right);
|
||||
|
||||
rightObj := FJsonObjectStack.Pop;
|
||||
leftObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('BinaryExpr'));
|
||||
obj.AddPair('Operator', TJSONString.Create(Node.Operator.ToString));
|
||||
obj.AddPair('Left', leftObj);
|
||||
obj.AddPair('Right', rightObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('BinaryExpr'));
|
||||
Result.AddPair('Operator', TJSONString.Create(Node.Operator.ToString));
|
||||
Result.AddPair('Left', leftObj);
|
||||
Result.AddPair('Right', rightObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
|
||||
function TJsonAstConverter.VisitUnaryExpression(const Node: IUnaryExpressionNode): TJSONObject;
|
||||
var
|
||||
obj, rightObj: TJSONObject;
|
||||
rightObj: TJSONObject;
|
||||
begin
|
||||
Node.Right.Accept(Self);
|
||||
rightObj := FJsonObjectStack.Pop;
|
||||
rightObj := Accept(Node.Right);
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('UnaryExpr'));
|
||||
obj.AddPair('Operator', TJSONString.Create(Node.Operator.ToString));
|
||||
obj.AddPair('Right', rightObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('UnaryExpr'));
|
||||
Result.AddPair('Operator', TJSONString.Create(Node.Operator.ToString));
|
||||
Result.AddPair('Right', rightObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||
function TJsonAstConverter.VisitIfExpression(const Node: IIfExpressionNode): TJSONObject;
|
||||
var
|
||||
obj, condObj, thenObj, elseObj: TJSONObject;
|
||||
condObj, thenObj, elseObj: TJSONObject;
|
||||
begin
|
||||
Node.Condition.Accept(Self);
|
||||
Node.ThenBranch.Accept(Self);
|
||||
if Assigned(Node.ElseBranch) then
|
||||
Node.ElseBranch.Accept(Self);
|
||||
condObj := Accept(Node.Condition);
|
||||
thenObj := Accept(Node.ThenBranch);
|
||||
elseObj := Accept(Node.ElseBranch); // Accept handles nil
|
||||
|
||||
if Assigned(Node.ElseBranch) then
|
||||
elseObj := FJsonObjectStack.Pop
|
||||
else
|
||||
elseObj := nil;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('IfExpr'));
|
||||
Result.AddPair('Condition', condObj);
|
||||
Result.AddPair('ThenBranch', thenObj);
|
||||
|
||||
thenObj := FJsonObjectStack.Pop;
|
||||
condObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('IfExpr'));
|
||||
obj.AddPair('Condition', condObj);
|
||||
obj.AddPair('ThenBranch', thenObj);
|
||||
if Assigned(elseObj) then
|
||||
obj.AddPair('ElseBranch', elseObj)
|
||||
Result.AddPair('ElseBranch', elseObj)
|
||||
else
|
||||
obj.AddPair('ElseBranch', TJSONNull.Create);
|
||||
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result.AddPair('ElseBranch', TJSONNull.Create);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||
function TJsonAstConverter.VisitTernaryExpression(const Node: ITernaryExpressionNode): TJSONObject;
|
||||
var
|
||||
obj, condObj, thenObj, elseObj: TJSONObject;
|
||||
condObj, thenObj, elseObj: TJSONObject;
|
||||
begin
|
||||
Node.Condition.Accept(Self);
|
||||
Node.ThenBranch.Accept(Self);
|
||||
Node.ElseBranch.Accept(Self);
|
||||
condObj := Accept(Node.Condition);
|
||||
thenObj := Accept(Node.ThenBranch);
|
||||
elseObj := Accept(Node.ElseBranch);
|
||||
|
||||
elseObj := FJsonObjectStack.Pop;
|
||||
thenObj := FJsonObjectStack.Pop;
|
||||
condObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('TernaryExpr'));
|
||||
obj.AddPair('Condition', condObj);
|
||||
obj.AddPair('ThenBranch', thenObj);
|
||||
obj.AddPair('ElseBranch', elseObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('TernaryExpr'));
|
||||
Result.AddPair('Condition', condObj);
|
||||
Result.AddPair('ThenBranch', thenObj);
|
||||
Result.AddPair('ElseBranch', elseObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||
function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject;
|
||||
var
|
||||
obj, bodyObj: TJSONObject;
|
||||
bodyObj: TJSONObject;
|
||||
paramsArray: TJSONArray;
|
||||
tempParams: TArray<TJSONObject>;
|
||||
param: IIdentifierNode;
|
||||
i: Integer;
|
||||
begin
|
||||
for param in Node.Parameters do
|
||||
param.Accept(Self);
|
||||
Node.Body.Accept(Self);
|
||||
|
||||
bodyObj := FJsonObjectStack.Pop;
|
||||
|
||||
SetLength(tempParams, Length(Node.Parameters));
|
||||
for i := High(tempParams) downto 0 do
|
||||
tempParams[i] := FJsonObjectStack.Pop;
|
||||
bodyObj := Accept(Node.Body);
|
||||
|
||||
paramsArray := TJSONArray.Create;
|
||||
for i := 0 to High(tempParams) do
|
||||
paramsArray.Add(tempParams[i]);
|
||||
for var param in Node.Parameters do
|
||||
paramsArray.Add(Accept(param));
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('LambdaExpr'));
|
||||
obj.AddPair('Parameters', paramsArray);
|
||||
obj.AddPair('Body', bodyObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('LambdaExpr'));
|
||||
Result.AddPair('Parameters', paramsArray);
|
||||
Result.AddPair('Body', bodyObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||
function TJsonAstConverter.VisitMacroDefinition(const Node: IMacroDefinitionNode): TJSONObject;
|
||||
var
|
||||
obj, nameObj, bodyObj: TJSONObject;
|
||||
nameObj, bodyObj: TJSONObject;
|
||||
paramsArray: TJSONArray;
|
||||
tempParams: TArray<TJSONObject>;
|
||||
param: IIdentifierNode;
|
||||
i: Integer;
|
||||
begin
|
||||
Node.Name.Accept(Self);
|
||||
for param in Node.Parameters do
|
||||
param.Accept(Self);
|
||||
Node.Body.Accept(Self);
|
||||
|
||||
bodyObj := FJsonObjectStack.Pop;
|
||||
|
||||
SetLength(tempParams, Length(Node.Parameters));
|
||||
for i := High(tempParams) downto 0 do
|
||||
tempParams[i] := FJsonObjectStack.Pop;
|
||||
|
||||
nameObj := FJsonObjectStack.Pop;
|
||||
nameObj := Accept(Node.Name);
|
||||
bodyObj := Accept(Node.Body);
|
||||
|
||||
paramsArray := TJSONArray.Create;
|
||||
for i := 0 to High(tempParams) do
|
||||
paramsArray.Add(tempParams[i]);
|
||||
for var param in Node.Parameters do
|
||||
paramsArray.Add(Accept(param));
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('MacroDef'));
|
||||
obj.AddPair('Name', nameObj);
|
||||
obj.AddPair('Parameters', paramsArray);
|
||||
obj.AddPair('Body', bodyObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('MacroDef'));
|
||||
Result.AddPair('Name', nameObj);
|
||||
Result.AddPair('Parameters', paramsArray);
|
||||
Result.AddPair('Body', bodyObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
|
||||
var
|
||||
obj, exprObj: TJSONObject;
|
||||
function TJsonAstConverter.VisitQuasiquote(const Node: IQuasiquoteNode): TJSONObject;
|
||||
begin
|
||||
Node.Expression.Accept(Self);
|
||||
exprObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('Quasiquote'));
|
||||
obj.AddPair('Expression', exprObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('Quasiquote'));
|
||||
Result.AddPair('Expression', Accept(Node.Expression));
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitUnquote(const Node: IUnquoteNode): TDataValue;
|
||||
var
|
||||
obj, exprObj: TJSONObject;
|
||||
function TJsonAstConverter.VisitUnquote(const Node: IUnquoteNode): TJSONObject;
|
||||
begin
|
||||
Node.Expression.Accept(Self);
|
||||
exprObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('Unquote'));
|
||||
obj.AddPair('Expression', exprObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('Unquote'));
|
||||
Result.AddPair('Expression', Accept(Node.Expression));
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
|
||||
var
|
||||
obj, exprObj: TJSONObject;
|
||||
function TJsonAstConverter.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TJSONObject;
|
||||
begin
|
||||
Node.Expression.Accept(Self);
|
||||
exprObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('UnquoteSplicing'));
|
||||
obj.AddPair('Expression', exprObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('UnquoteSplicing'));
|
||||
Result.AddPair('Expression', Accept(Node.Expression));
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||
function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TJSONObject;
|
||||
var
|
||||
obj, calleeObj: TJSONObject;
|
||||
calleeObj: TJSONObject;
|
||||
argsArray: TJSONArray;
|
||||
tempArgs: TArray<TJSONObject>;
|
||||
arg: IAstNode;
|
||||
i: Integer;
|
||||
begin
|
||||
Node.Callee.Accept(Self);
|
||||
for arg in Node.Arguments do
|
||||
arg.Accept(Self);
|
||||
|
||||
SetLength(tempArgs, Length(Node.Arguments));
|
||||
for i := High(tempArgs) downto 0 do
|
||||
tempArgs[i] := FJsonObjectStack.Pop;
|
||||
calleeObj := Accept(Node.Callee);
|
||||
|
||||
argsArray := TJSONArray.Create;
|
||||
for i := 0 to High(tempArgs) do
|
||||
argsArray.Add(tempArgs[i]);
|
||||
for arg in Node.Arguments do
|
||||
argsArray.Add(Accept(arg));
|
||||
|
||||
calleeObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('FunctionCall'));
|
||||
obj.AddPair('Callee', calleeObj);
|
||||
obj.AddPair('Arguments', argsArray);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('FunctionCall'));
|
||||
Result.AddPair('Callee', calleeObj);
|
||||
Result.AddPair('Arguments', argsArray);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
||||
function TJsonAstConverter.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TJSONObject;
|
||||
var
|
||||
obj, calleeObj, bodyObj: TJSONObject;
|
||||
calleeObj, bodyObj: TJSONObject;
|
||||
argsArray: TJSONArray;
|
||||
tempArgs: TArray<TJSONObject>;
|
||||
arg: IAstNode;
|
||||
i: Integer;
|
||||
begin
|
||||
// Serialize all children first: Callee, Arguments, and the new ExpandedBody
|
||||
Node.Callee.Accept(Self);
|
||||
for arg in Node.Arguments do
|
||||
arg.Accept(Self);
|
||||
Node.ExpandedBody.Accept(Self);
|
||||
|
||||
// Pop children's JSON from stack in reverse order of visitation
|
||||
bodyObj := FJsonObjectStack.Pop;
|
||||
|
||||
SetLength(tempArgs, Length(Node.Arguments));
|
||||
for i := High(tempArgs) downto 0 do
|
||||
tempArgs[i] := FJsonObjectStack.Pop;
|
||||
|
||||
calleeObj := FJsonObjectStack.Pop;
|
||||
|
||||
// Build JSON array for arguments
|
||||
argsArray := TJSONArray.Create;
|
||||
for var argObj in tempArgs do
|
||||
argsArray.Add(argObj);
|
||||
|
||||
// Create the final JSON object for this node
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('MacroExpansion'));
|
||||
obj.AddPair('Callee', calleeObj);
|
||||
obj.AddPair('Arguments', argsArray);
|
||||
obj.AddPair('ExpandedBody', bodyObj);
|
||||
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitRecurNode(const Node: IRecurNode): TDataValue;
|
||||
var
|
||||
obj: TJSONObject;
|
||||
argsArray: TJSONArray;
|
||||
tempArgs: TArray<TJSONObject>;
|
||||
arg: IAstNode;
|
||||
i: Integer;
|
||||
begin
|
||||
for arg in Node.Arguments do
|
||||
arg.Accept(Self);
|
||||
|
||||
SetLength(tempArgs, Length(Node.Arguments));
|
||||
for i := High(tempArgs) downto 0 do
|
||||
tempArgs[i] := FJsonObjectStack.Pop;
|
||||
calleeObj := Accept(Node.Callee);
|
||||
bodyObj := Accept(Node.ExpandedBody);
|
||||
|
||||
argsArray := TJSONArray.Create;
|
||||
for i := 0 to High(tempArgs) do
|
||||
argsArray.Add(tempArgs[i]);
|
||||
for arg in Node.Arguments do
|
||||
argsArray.Add(Accept(arg));
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('Recur'));
|
||||
obj.AddPair('Arguments', argsArray);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('MacroExpansion'));
|
||||
Result.AddPair('Callee', calleeObj);
|
||||
Result.AddPair('Arguments', argsArray);
|
||||
Result.AddPair('ExpandedBody', bodyObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||
function TJsonAstConverter.VisitRecurNode(const Node: IRecurNode): TJSONObject;
|
||||
var
|
||||
argsArray: TJSONArray;
|
||||
arg: IAstNode;
|
||||
begin
|
||||
argsArray := TJSONArray.Create;
|
||||
for arg in Node.Arguments do
|
||||
argsArray.Add(Accept(arg));
|
||||
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('Recur'));
|
||||
Result.AddPair('Arguments', argsArray);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitBlockExpression(const Node: IBlockExpressionNode): TJSONObject;
|
||||
var
|
||||
obj: TJSONObject;
|
||||
exprsArray: TJSONArray;
|
||||
tempExprs: TArray<TJSONObject>;
|
||||
expr: IAstNode;
|
||||
i: Integer;
|
||||
begin
|
||||
for expr in Node.Expressions do
|
||||
expr.Accept(Self);
|
||||
|
||||
SetLength(tempExprs, Length(Node.Expressions));
|
||||
for i := High(tempExprs) downto 0 do
|
||||
tempExprs[i] := FJsonObjectStack.Pop;
|
||||
|
||||
exprsArray := TJSONArray.Create;
|
||||
for i := 0 to High(tempExprs) do
|
||||
exprsArray.Add(tempExprs[i]);
|
||||
for expr in Node.Expressions do
|
||||
exprsArray.Add(Accept(expr));
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('Block'));
|
||||
obj.AddPair('Expressions', exprsArray);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('Block'));
|
||||
Result.AddPair('Expressions', exprsArray);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||
function TJsonAstConverter.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TJSONObject;
|
||||
var
|
||||
obj, identObj, initObj: TJSONObject;
|
||||
identObj, initObj: TJSONObject;
|
||||
begin
|
||||
Node.Identifier.Accept(Self);
|
||||
if Assigned(Node.Initializer) then
|
||||
Node.Initializer.Accept(Self);
|
||||
identObj := Accept(Node.Identifier);
|
||||
initObj := Accept(Node.Initializer); // Accept handles nil
|
||||
|
||||
if Assigned(Node.Initializer) then
|
||||
initObj := FJsonObjectStack.Pop
|
||||
else
|
||||
initObj := nil;
|
||||
identObj := FJsonObjectStack.Pop;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('VarDecl'));
|
||||
Result.AddPair('Identifier', identObj);
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('VarDecl'));
|
||||
obj.AddPair('Identifier', identObj);
|
||||
if Assigned(initObj) then
|
||||
obj.AddPair('Initializer', initObj)
|
||||
Result.AddPair('Initializer', initObj)
|
||||
else
|
||||
obj.AddPair('Initializer', TJSONNull.Create);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result.AddPair('Initializer', TJSONNull.Create);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitAssignment(const Node: IAssignmentNode): TDataValue;
|
||||
function TJsonAstConverter.VisitAssignment(const Node: IAssignmentNode): TJSONObject;
|
||||
var
|
||||
obj, identObj, valueObj: TJSONObject;
|
||||
identObj, valueObj: TJSONObject;
|
||||
begin
|
||||
Node.Identifier.Accept(Self);
|
||||
Node.Value.Accept(Self);
|
||||
identObj := Accept(Node.Identifier);
|
||||
valueObj := Accept(Node.Value);
|
||||
|
||||
valueObj := FJsonObjectStack.Pop;
|
||||
identObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('Assignment'));
|
||||
obj.AddPair('Identifier', identObj);
|
||||
obj.AddPair('Value', valueObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('Assignment'));
|
||||
Result.AddPair('Identifier', identObj);
|
||||
Result.AddPair('Value', valueObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||
function TJsonAstConverter.VisitIndexer(const Node: IIndexerNode): TJSONObject;
|
||||
var
|
||||
obj, baseObj, indexObj: TJSONObject;
|
||||
baseObj, indexObj: TJSONObject;
|
||||
begin
|
||||
Node.Base.Accept(Self);
|
||||
Node.Index.Accept(Self);
|
||||
baseObj := Accept(Node.Base);
|
||||
indexObj := Accept(Node.Index);
|
||||
|
||||
indexObj := FJsonObjectStack.Pop;
|
||||
baseObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('Indexer'));
|
||||
obj.AddPair('Base', baseObj);
|
||||
obj.AddPair('Index', indexObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('Indexer'));
|
||||
Result.AddPair('Base', baseObj);
|
||||
Result.AddPair('Index', indexObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
||||
function TJsonAstConverter.VisitMemberAccess(const Node: IMemberAccessNode): TJSONObject;
|
||||
var
|
||||
obj, baseObj, memberObj: TJSONObject;
|
||||
baseObj, memberObj: TJSONObject;
|
||||
begin
|
||||
Node.Base.Accept(Self);
|
||||
Node.Member.Accept(Self);
|
||||
baseObj := Accept(Node.Base);
|
||||
memberObj := Accept(Node.Member);
|
||||
|
||||
memberObj := FJsonObjectStack.Pop;
|
||||
baseObj := FJsonObjectStack.Pop;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('MemberAccess'));
|
||||
obj.AddPair('Base', baseObj);
|
||||
obj.AddPair('Member', memberObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('MemberAccess'));
|
||||
Result.AddPair('Base', baseObj);
|
||||
Result.AddPair('Member', memberObj);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
|
||||
function TJsonAstConverter.VisitRecordLiteral(const Node: IRecordLiteralNode): TJSONObject;
|
||||
var
|
||||
obj, fieldObj: TJSONObject;
|
||||
fieldsArray: TJSONArray;
|
||||
field: TRecordFieldLiteral;
|
||||
fieldObj: TJSONObject;
|
||||
begin
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('RecordLiteral'));
|
||||
Result := TJSONObject.Create;
|
||||
Result.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.Key.Value.Name));
|
||||
fieldObj.AddPair('Value', FJsonObjectStack.Pop);
|
||||
fieldObj.AddPair('Value', Accept(field.Value)); // Get TJSONObject
|
||||
fieldsArray.Add(fieldObj);
|
||||
end;
|
||||
|
||||
obj.AddPair('Fields', fieldsArray);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result.AddPair('Fields', fieldsArray);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
||||
var
|
||||
obj: TJSONObject;
|
||||
function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TJSONObject;
|
||||
begin
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('CreateSeries'));
|
||||
obj.AddPair('Definition', TJSONString.Create(Node.Definition));
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('CreateSeries'));
|
||||
Result.AddPair('Definition', TJSONString.Create(Node.Definition));
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
||||
function TJsonAstConverter.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TJSONObject;
|
||||
var
|
||||
obj, seriesObj, valueObj, lookbackObj: TJSONObject;
|
||||
seriesObj, valueObj, lookbackObj: TJSONObject;
|
||||
begin
|
||||
Node.Series.Accept(Self);
|
||||
Node.Value.Accept(Self);
|
||||
if Assigned(Node.Lookback) then
|
||||
Node.Lookback.Accept(Self);
|
||||
seriesObj := Accept(Node.Series);
|
||||
valueObj := Accept(Node.Value);
|
||||
lookbackObj := Accept(Node.Lookback); // Accept handles nil
|
||||
|
||||
if Assigned(Node.Lookback) then
|
||||
lookbackObj := FJsonObjectStack.Pop
|
||||
else
|
||||
lookbackObj := nil;
|
||||
valueObj := FJsonObjectStack.Pop;
|
||||
seriesObj := FJsonObjectStack.Pop;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('AddSeriesItem'));
|
||||
Result.AddPair('Series', seriesObj);
|
||||
Result.AddPair('Value', valueObj);
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('AddSeriesItem'));
|
||||
obj.AddPair('Series', seriesObj);
|
||||
obj.AddPair('Value', valueObj);
|
||||
if Assigned(lookbackObj) then
|
||||
obj.AddPair('Lookback', lookbackObj)
|
||||
Result.AddPair('Lookback', lookbackObj)
|
||||
else
|
||||
obj.AddPair('Lookback', TJSONNull.Create);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result.AddPair('Lookback', TJSONNull.Create);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||
function TJsonAstConverter.VisitSeriesLength(const Node: ISeriesLengthNode): TJSONObject;
|
||||
var
|
||||
obj, seriesObj: TJSONObject;
|
||||
seriesObj: TJSONObject;
|
||||
begin
|
||||
Node.Series.Accept(Self);
|
||||
seriesObj := FJsonObjectStack.Pop;
|
||||
seriesObj := Accept(Node.Series);
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('SeriesLength'));
|
||||
obj.AddPair('Series', seriesObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
Result := TJSONObject.Create;
|
||||
Result.AddPair('NodeType', TJSONString.Create('SeriesLength'));
|
||||
Result.AddPair('Series', seriesObj);
|
||||
end;
|
||||
|
||||
{ TJsonAstConverter - Deserialization }
|
||||
@@ -827,7 +636,7 @@ end;
|
||||
|
||||
function TJsonAstConverter.JsonToUnquoteSplicingNode(const AObj: TJSONObject): IUnquoteSplicingNode;
|
||||
begin
|
||||
Result := TAst.UnquoteSplicing(JsonToNode(AObj.GetValue('Expression')));
|
||||
Result := TAst.UnquoteSplicing(JsonToNode(AObj.GetValue('Expression')).AsQuasiquote);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
|
||||
@@ -1020,16 +829,12 @@ end;
|
||||
|
||||
function TJsonAstConverter.Serialize(const RootNode: IAstNode): TJSONObject;
|
||||
begin
|
||||
FJsonObjectStack.Clear;
|
||||
if not Assigned(RootNode) then
|
||||
exit(nil);
|
||||
|
||||
RootNode.Accept(Self);
|
||||
|
||||
if FJsonObjectStack.Count <> 1 then
|
||||
raise EInvalidOpException.Create('JSON serialization stack is corrupt.');
|
||||
|
||||
Result := FJsonObjectStack.Pop;
|
||||
// Call Accept, which returns TDataValue(vkGeneric(TJSONObject))
|
||||
// and unwrap it.
|
||||
Result := RootNode.Accept(Self).AsGeneric<TJSONObject>;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user