Macro expander integrated in binder
This commit is contained in:
+102
-36
@@ -39,6 +39,7 @@ type
|
||||
function JsonToUnquoteNode(const AObj: TJSONObject): IUnquoteNode;
|
||||
function JsonToUnquoteSplicingNode(const AObj: TJSONObject): IUnquoteSplicingNode;
|
||||
function JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
|
||||
function JsonToMacroExpansionNode(const AObj: TJSONObject): IMacroExpansionNode;
|
||||
function JsonToRecurNode(const AObj: TJSONObject): IRecurNode;
|
||||
function JsonToBlockNode(const AObj: TJSONObject): IBlockExpressionNode;
|
||||
function JsonToVarDeclNode(const AObj: TJSONObject): IVariableDeclarationNode;
|
||||
@@ -62,6 +63,7 @@ type
|
||||
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;
|
||||
@@ -301,19 +303,46 @@ begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.JsonToQuasiquoteNode(const AObj: TJSONObject): IQuasiquoteNode;
|
||||
function TJsonAstConverter.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
|
||||
var
|
||||
obj, exprObj: TJSONObject;
|
||||
begin
|
||||
Result := TAst.Quasiquote(JsonToNode(AObj.GetValue('Expression')));
|
||||
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;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.JsonToUnquoteNode(const AObj: TJSONObject): IUnquoteNode;
|
||||
function TJsonAstConverter.VisitUnquote(const Node: IUnquoteNode): TDataValue;
|
||||
var
|
||||
obj, exprObj: TJSONObject;
|
||||
begin
|
||||
Result := TAst.Unquote(JsonToNode(AObj.GetValue('Expression')));
|
||||
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;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.JsonToUnquoteSplicingNode(const AObj: TJSONObject): IUnquoteSplicingNode;
|
||||
function TJsonAstConverter.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
|
||||
var
|
||||
obj, exprObj: TJSONObject;
|
||||
begin
|
||||
Result := TAst.UnquoteSplicing(JsonToNode(AObj.GetValue('Expression')));
|
||||
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;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||
@@ -346,6 +375,45 @@ begin
|
||||
Result := TDataValue.Void;
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
||||
var
|
||||
obj, 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;
|
||||
@@ -667,46 +735,42 @@ begin
|
||||
Result := TAst.MacroDef(name, params, body);
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
|
||||
function TJsonAstConverter.JsonToMacroExpansionNode(const AObj: TJSONObject): IMacroExpansionNode;
|
||||
var
|
||||
obj, exprObj: TJSONObject;
|
||||
callee, expandedBody: IAstNode;
|
||||
args: TArray<IAstNode>;
|
||||
argsArray: TJSONArray;
|
||||
i: Integer;
|
||||
tempCallNode: IFunctionCallNode;
|
||||
begin
|
||||
Node.Expression.Accept(Self);
|
||||
exprObj := FJsonObjectStack.Pop;
|
||||
// Recursively deserialize all parts of the macro expansion node
|
||||
callee := JsonToNode(AObj.GetValue('Callee'));
|
||||
expandedBody := JsonToNode(AObj.GetValue('ExpandedBody'));
|
||||
argsArray := AObj.GetValue<TJSONArray>('Arguments');
|
||||
SetLength(args, argsArray.Count);
|
||||
for i := 0 to argsArray.Count - 1 do
|
||||
args[i] := JsonToNode(argsArray.Items[i]);
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('Quasiquote'));
|
||||
obj.AddPair('Expression', exprObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
// 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;
|
||||
|
||||
function TJsonAstConverter.VisitUnquote(const Node: IUnquoteNode): TDataValue;
|
||||
var
|
||||
obj, exprObj: TJSONObject;
|
||||
function TJsonAstConverter.JsonToQuasiquoteNode(const AObj: TJSONObject): IQuasiquoteNode;
|
||||
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 := TAst.Quasiquote(JsonToNode(AObj.GetValue('Expression')));
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
|
||||
var
|
||||
obj, exprObj: TJSONObject;
|
||||
function TJsonAstConverter.JsonToUnquoteNode(const AObj: TJSONObject): IUnquoteNode;
|
||||
begin
|
||||
Node.Expression.Accept(Self);
|
||||
exprObj := FJsonObjectStack.Pop;
|
||||
Result := TAst.Unquote(JsonToNode(AObj.GetValue('Expression')));
|
||||
end;
|
||||
|
||||
obj := TJSONObject.Create;
|
||||
obj.AddPair('NodeType', TJSONString.Create('UnquoteSplicing'));
|
||||
obj.AddPair('Expression', exprObj);
|
||||
FJsonObjectStack.Push(obj);
|
||||
Result := TDataValue.Void;
|
||||
function TJsonAstConverter.JsonToUnquoteSplicingNode(const AObj: TJSONObject): IUnquoteSplicingNode;
|
||||
begin
|
||||
Result := TAst.UnquoteSplicing(JsonToNode(AObj.GetValue('Expression')));
|
||||
end;
|
||||
|
||||
function TJsonAstConverter.JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
|
||||
@@ -837,6 +901,8 @@ begin
|
||||
Result := JsonToLambdaExprNode(obj)
|
||||
else if nodeType = 'MacroDef' then
|
||||
Result := JsonToMacroDefNode(obj)
|
||||
else if nodeType = 'MacroExpansion' then
|
||||
Result := JsonToMacroExpansionNode(obj)
|
||||
else if nodeType = 'Quasiquote' then
|
||||
Result := JsonToQuasiquoteNode(obj)
|
||||
else if nodeType = 'Unquote' then
|
||||
|
||||
Reference in New Issue
Block a user