added macrodef
This commit is contained in:
@@ -20,6 +20,7 @@ type
|
|||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
||||||
@@ -164,6 +165,33 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstToTextVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
sb: TStringBuilder;
|
||||||
|
begin
|
||||||
|
// Added text representation for macro definitions.
|
||||||
|
sb := TStringBuilder.Create;
|
||||||
|
try
|
||||||
|
sb.Append('defmacro ');
|
||||||
|
sb.Append(Node.Name.Name);
|
||||||
|
sb.Append('(');
|
||||||
|
if Length(Node.Parameters) > 0 then
|
||||||
|
begin
|
||||||
|
for i := 0 to High(Node.Parameters) do
|
||||||
|
begin
|
||||||
|
sb.Append(Node.Parameters[i].Name);
|
||||||
|
if i < High(Node.Parameters) then
|
||||||
|
sb.Append(', ');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
sb.Append(') => {...}');
|
||||||
|
Result := sb.ToString;
|
||||||
|
finally
|
||||||
|
sb.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
||||||
var
|
var
|
||||||
baseStr: string;
|
baseStr: string;
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ type
|
|||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
||||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
|
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
|
||||||
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
|
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
|
||||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
|
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
|
||||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
|
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
|
||||||
@@ -1147,6 +1148,103 @@ begin
|
|||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstToAuraNodeVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
|
var
|
||||||
|
paramStr: String;
|
||||||
|
macroNode: TAuraNode;
|
||||||
|
i: Integer;
|
||||||
|
childVisitor: TAstToAuraNodeVisitor;
|
||||||
|
childStartPos: TPointF;
|
||||||
|
maxRight, maxBottom: Single;
|
||||||
|
control: TControl;
|
||||||
|
childLastResult: TAuraNodeResult;
|
||||||
|
entryNode, exitNode: TAuraNode;
|
||||||
|
paramDescriptor: IScopeDescriptor;
|
||||||
|
begin
|
||||||
|
// Create a string representation of the parameters for the node title.
|
||||||
|
paramStr := '(';
|
||||||
|
if Length(Node.Parameters) > 0 then
|
||||||
|
begin
|
||||||
|
paramStr := paramStr + Node.Parameters[0].Name;
|
||||||
|
for i := 1 to High(Node.Parameters) do
|
||||||
|
paramStr := paramStr + ', ' + Node.Parameters[i].Name;
|
||||||
|
end;
|
||||||
|
paramStr := paramStr + ')';
|
||||||
|
|
||||||
|
// 1. Create the main container node for the macro definition.
|
||||||
|
macroNode := BuildNodeControl('defmacro: ' + Node.Name.Name, paramStr);
|
||||||
|
macroNode.Position.Point := FCurrentPos;
|
||||||
|
|
||||||
|
// A macro definition is a statement, so it has execution pins.
|
||||||
|
CreateEntry(macroNode);
|
||||||
|
|
||||||
|
// 2. Create a temporary scope descriptor for the macro's parameters.
|
||||||
|
// This allows the child visitor to correctly visualize parameter nodes.
|
||||||
|
paramDescriptor := TScope.CreateDescriptor(nil);
|
||||||
|
for i := 0 to High(Node.Parameters) do
|
||||||
|
paramDescriptor.Define(Node.Parameters[i].Name);
|
||||||
|
|
||||||
|
// 3. Create a child visitor for the new scope within the macro's body.
|
||||||
|
const pinNodeHeight = cPinSize + cVerticalPadding;
|
||||||
|
childStartPos := TPointF.Create(FSpacing.X, FSpacing.Y + pinNodeHeight);
|
||||||
|
childVisitor := TAstToAuraNodeVisitor.Create(FWorkspace, macroNode, childStartPos, FConnections, [], FMode, Self, nil, paramDescriptor);
|
||||||
|
|
||||||
|
// 4. Create the visual nodes for the parameters inside the macro's scope.
|
||||||
|
for i := 0 to High(Node.Parameters) do
|
||||||
|
begin
|
||||||
|
var param := Node.Parameters[i];
|
||||||
|
var paramNode := childVisitor.CreateNodeControl('Parameter', param.Name);
|
||||||
|
var paramResult: TAuraNodeResult;
|
||||||
|
paramResult.LayoutNode := paramNode;
|
||||||
|
paramResult.OutputPin := childVisitor.CreateOutput(paramNode);
|
||||||
|
childVisitor.FinalizeNodeLayout(paramNode);
|
||||||
|
// Cache the parameter node by its slot index for lookups within the body.
|
||||||
|
if i < Length(childVisitor.FSlotCache) then
|
||||||
|
childVisitor.FSlotCache[i] := paramResult;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// 5. Let the child visitor render the macro's body.
|
||||||
|
Node.Body.Accept(childVisitor);
|
||||||
|
childLastResult := childVisitor.FLastResult;
|
||||||
|
|
||||||
|
// 6. Resize the container to fit all internally generated nodes.
|
||||||
|
maxRight := 0;
|
||||||
|
maxBottom := 0;
|
||||||
|
for control in macroNode.Controls do
|
||||||
|
begin
|
||||||
|
if control is TAuraNode then
|
||||||
|
begin
|
||||||
|
maxRight := Max(maxRight, control.Position.X + control.Width);
|
||||||
|
maxBottom := Max(maxBottom, control.Position.Y + control.Height);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
macroNode.Width := Max(macroNode.Width, maxRight + FSpacing.X);
|
||||||
|
macroNode.Height := Max(macroNode.Height, maxBottom + FSpacing.Y);
|
||||||
|
|
||||||
|
// 7. Create an internal 'expansion' exit point, showing what the macro produces.
|
||||||
|
exitNode := BuildNodeControl('Expansion', '');
|
||||||
|
exitNode.Parent := macroNode;
|
||||||
|
exitNode.Height := pinNodeHeight;
|
||||||
|
// Connect the data flow (the result of the last expression in the body) to the expansion node.
|
||||||
|
if Assigned(childLastResult.OutputPin) then
|
||||||
|
begin
|
||||||
|
var dataResultPin := childVisitor.CreateInput(exitNode, 'AST');
|
||||||
|
FConnections.Add(TPinConnection.Create(childLastResult.OutputPin, dataResultPin));
|
||||||
|
end;
|
||||||
|
childVisitor.FinalizeNodeLayout(exitNode);
|
||||||
|
macroNode.Height := Max(macroNode.Height, maxBottom + FSpacing.Y + exitNode.Height);
|
||||||
|
exitNode.Position.Point := TPointF.Create(FSpacing.X, macroNode.Height - exitNode.Height - FSpacing.Y);
|
||||||
|
|
||||||
|
// 8. Finalize the main visitor state.
|
||||||
|
FCurrentPos.Y := macroNode.Position.Y + macroNode.Height + FSpacing.Y;
|
||||||
|
FLastResult.LayoutNode := macroNode;
|
||||||
|
FLastResult.OutputPin := nil; // A macro definition itself does not return a value.
|
||||||
|
CreateExit(macroNode, ''); // Execution flow continues after the definition.
|
||||||
|
FinalizeNodeLayout(macroNode);
|
||||||
|
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstToAuraNodeVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
function TAstToAuraNodeVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||||
var
|
var
|
||||||
details: string;
|
details: string;
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ type
|
|||||||
function TransformVariableDeclaration(const Node: IVariableDeclarationNode): IVariableDeclarationNode; override;
|
function TransformVariableDeclaration(const Node: IVariableDeclarationNode): IVariableDeclarationNode; override;
|
||||||
function TransformAssignment(const Node: IAssignmentNode): IAssignmentNode; override;
|
function TransformAssignment(const Node: IAssignmentNode): IAssignmentNode; override;
|
||||||
function TransformLambdaExpression(const Node: ILambdaExpressionNode): ILambdaExpressionNode; override;
|
function TransformLambdaExpression(const Node: ILambdaExpressionNode): ILambdaExpressionNode; override;
|
||||||
|
function TransformMacroDefinition(const Node: IMacroDefinitionNode): IMacroDefinitionNode; override;
|
||||||
function TransformFunctionCall(const Node: IFunctionCallNode): IFunctionCallNode; override;
|
function TransformFunctionCall(const Node: IFunctionCallNode): IFunctionCallNode; override;
|
||||||
function TransformRecur(const Node: IRecurNode): IRecurNode; override;
|
function TransformRecur(const Node: IRecurNode): IRecurNode; override;
|
||||||
function TransformBlockExpression(const Node: IBlockExpressionNode): IBlockExpressionNode; override;
|
function TransformBlockExpression(const Node: IBlockExpressionNode): IBlockExpressionNode; override;
|
||||||
@@ -478,6 +479,12 @@ begin
|
|||||||
Result := Node;
|
Result := Node;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstBinder.TransformMacroDefinition(const Node: IMacroDefinitionNode): IMacroDefinitionNode;
|
||||||
|
begin
|
||||||
|
// The binder runs after the macro expander. It should never see a macro definition.
|
||||||
|
raise Exception.Create('IMacroDefinitionNode found in AST after macro expansion phase.');
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstBinder.TransformTernaryExpression(const Node: ITernaryExpressionNode): ITernaryExpressionNode;
|
function TAstBinder.TransformTernaryExpression(const Node: ITernaryExpressionNode): ITernaryExpressionNode;
|
||||||
var
|
var
|
||||||
isContextTail: Boolean;
|
isContextTail: Boolean;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ type
|
|||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
||||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
|
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
|
||||||
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
|
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
|
||||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
|
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
|
||||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
|
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
|
||||||
@@ -322,6 +323,33 @@ begin
|
|||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstDumper.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
|
var
|
||||||
|
param: IIdentifierNode;
|
||||||
|
begin
|
||||||
|
Log('MacroDefinition');
|
||||||
|
Indent;
|
||||||
|
|
||||||
|
Log('Name:');
|
||||||
|
Indent;
|
||||||
|
Node.Name.Accept(Self);
|
||||||
|
Unindent;
|
||||||
|
|
||||||
|
Log('Parameters:');
|
||||||
|
Indent;
|
||||||
|
for param in Node.Parameters do
|
||||||
|
param.Accept(Self);
|
||||||
|
Unindent;
|
||||||
|
|
||||||
|
Log('Body:');
|
||||||
|
Indent;
|
||||||
|
Node.Body.Accept(Self);
|
||||||
|
Unindent;
|
||||||
|
|
||||||
|
Unindent;
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstDumper.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
function TAstDumper.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Log('Indexer');
|
Log('Indexer');
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ type
|
|||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
||||||
@@ -240,6 +241,14 @@ begin
|
|||||||
Result := closure;
|
Result := closure;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
|
begin
|
||||||
|
// Macro definitions are compile-time constructs and should have been
|
||||||
|
// processed and removed from the AST by the TMacroExpander.
|
||||||
|
// If we encounter one here, it's a compiler pipeline error.
|
||||||
|
raise Exception.Create('Macro definitions cannot be evaluated at runtime.');
|
||||||
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||||
var
|
var
|
||||||
calleeValue: TDataValue;
|
calleeValue: TDataValue;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type
|
|||||||
function JsonToIfExprNode(const AObj: TJSONObject): IIfExpressionNode;
|
function JsonToIfExprNode(const AObj: TJSONObject): IIfExpressionNode;
|
||||||
function JsonToTernaryExprNode(const AObj: TJSONObject): ITernaryExpressionNode;
|
function JsonToTernaryExprNode(const AObj: TJSONObject): ITernaryExpressionNode;
|
||||||
function JsonToLambdaExprNode(const AObj: TJSONObject): ILambdaExpressionNode;
|
function JsonToLambdaExprNode(const AObj: TJSONObject): ILambdaExpressionNode;
|
||||||
|
function JsonToMacroDefNode(const AObj: TJSONObject): IMacroDefinitionNode;
|
||||||
function JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
|
function JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
|
||||||
function JsonToRecurNode(const AObj: TJSONObject): IRecurNode;
|
function JsonToRecurNode(const AObj: TJSONObject): IRecurNode;
|
||||||
function JsonToBlockNode(const AObj: TJSONObject): IBlockExpressionNode;
|
function JsonToBlockNode(const AObj: TJSONObject): IBlockExpressionNode;
|
||||||
@@ -53,6 +54,7 @@ type
|
|||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
||||||
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
|
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
||||||
@@ -258,6 +260,41 @@ begin
|
|||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TJsonAstConverter.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
|
var
|
||||||
|
obj, nameObj, bodyObj: TJSONObject;
|
||||||
|
paramsArray: TJSONArray;
|
||||||
|
tempParams: TArray<TJSONObject>;
|
||||||
|
param: IIdentifierNode;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
// Added serialization for macro definitions.
|
||||||
|
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;
|
||||||
|
|
||||||
|
paramsArray := TJSONArray.Create;
|
||||||
|
for i := 0 to High(tempParams) do
|
||||||
|
paramsArray.Add(tempParams[i]);
|
||||||
|
|
||||||
|
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;
|
||||||
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||||
var
|
var
|
||||||
obj, calleeObj: TJSONObject;
|
obj, calleeObj: TJSONObject;
|
||||||
@@ -589,6 +626,26 @@ begin
|
|||||||
Result := TAst.LambdaExpr(params, body);
|
Result := TAst.LambdaExpr(params, body);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TJsonAstConverter.JsonToMacroDefNode(const AObj: TJSONObject): IMacroDefinitionNode;
|
||||||
|
var
|
||||||
|
name: IIdentifierNode;
|
||||||
|
params: TArray<IIdentifierNode>;
|
||||||
|
body: IAstNode;
|
||||||
|
paramArray: TJSONArray;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
// Added deserialization for macro definitions.
|
||||||
|
name := JsonToIdentifierNode(AObj.GetValue('Name') as TJSONObject);
|
||||||
|
|
||||||
|
paramArray := AObj.GetValue<TJSONArray>('Parameters');
|
||||||
|
SetLength(params, paramArray.Count);
|
||||||
|
for i := 0 to paramArray.Count - 1 do
|
||||||
|
params[i] := JsonToIdentifierNode(paramArray.Items[i] as TJSONObject);
|
||||||
|
|
||||||
|
body := JsonToNode(AObj.GetValue('Body'));
|
||||||
|
Result := TAst.MacroDef(name, params, body);
|
||||||
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
|
function TJsonAstConverter.JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
|
||||||
var
|
var
|
||||||
callee: IAstNode;
|
callee: IAstNode;
|
||||||
@@ -715,6 +772,8 @@ begin
|
|||||||
Result := JsonToTernaryExprNode(obj)
|
Result := JsonToTernaryExprNode(obj)
|
||||||
else if nodeType = 'LambdaExpr' then
|
else if nodeType = 'LambdaExpr' then
|
||||||
Result := JsonToLambdaExprNode(obj)
|
Result := JsonToLambdaExprNode(obj)
|
||||||
|
else if nodeType = 'MacroDef' then
|
||||||
|
Result := JsonToMacroDefNode(obj)
|
||||||
else if nodeType = 'FunctionCall' then
|
else if nodeType = 'FunctionCall' then
|
||||||
Result := JsonToFunctionCallNode(obj)
|
Result := JsonToFunctionCallNode(obj)
|
||||||
else if nodeType = 'Recur' then
|
else if nodeType = 'Recur' then
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type
|
|||||||
IBlockExpressionNode = interface;
|
IBlockExpressionNode = interface;
|
||||||
IVariableDeclarationNode = interface;
|
IVariableDeclarationNode = interface;
|
||||||
IAssignmentNode = interface;
|
IAssignmentNode = interface;
|
||||||
|
IMacroDefinitionNode = interface;
|
||||||
IIndexerNode = interface;
|
IIndexerNode = interface;
|
||||||
IMemberAccessNode = interface;
|
IMemberAccessNode = interface;
|
||||||
ICreateSeriesNode = interface;
|
ICreateSeriesNode = interface;
|
||||||
@@ -57,6 +58,7 @@ type
|
|||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue;
|
function VisitAssignment(const Node: IAssignmentNode): TDataValue;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
function VisitIndexer(const Node: IIndexerNode): TDataValue;
|
function VisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
||||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
||||||
@@ -177,6 +179,17 @@ type
|
|||||||
property Value: IAstNode read GetValue;
|
property Value: IAstNode read GetValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
IMacroDefinitionNode = interface(IAstNode)
|
||||||
|
{$region 'private'}
|
||||||
|
function GetName: IIdentifierNode;
|
||||||
|
function GetParameters: TArray<IIdentifierNode>;
|
||||||
|
function GetBody: IAstNode;
|
||||||
|
{$endregion}
|
||||||
|
property Name: IIdentifierNode read GetName;
|
||||||
|
property Parameters: TArray<IIdentifierNode> read GetParameters;
|
||||||
|
property Body: IAstNode read GetBody;
|
||||||
|
end;
|
||||||
|
|
||||||
IIndexerNode = interface(IAstNode)
|
IIndexerNode = interface(IAstNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetBase: IAstNode;
|
function GetBase: IAstNode;
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ type
|
|||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||||
@@ -359,6 +360,20 @@ begin
|
|||||||
raise Exception.Create('Syntax Error: Expected an identifier for def statement.');
|
raise Exception.Create('Syntax Error: Expected an identifier for def statement.');
|
||||||
Result := TAst.VarDecl(IIdentifierNode(tailNodes[0]), IfThen(Length(tailNodes) > 1, tailNodes[1], nil));
|
Result := TAst.VarDecl(IIdentifierNode(tailNodes[0]), IfThen(Length(tailNodes) > 1, tailNodes[1], nil));
|
||||||
end
|
end
|
||||||
|
else if SameText(head.Token.Text, 'defmacro') then
|
||||||
|
begin
|
||||||
|
// (defmacro name [params] body)
|
||||||
|
if (Length(tailNodes) <> 3) or (tailTokens[0].Kind <> tkIdentifier) then
|
||||||
|
raise Exception.Create('Syntax Error: ''defmacro'' requires a name, a parameter list, and a body.');
|
||||||
|
if elements[1].Node <> nil then
|
||||||
|
raise Exception.Create('Syntax Error: Expected a parameter list [...] after macro name.');
|
||||||
|
|
||||||
|
var macroName := IIdentifierNode(tailNodes[0]);
|
||||||
|
var macroParams := elements[1].Params;
|
||||||
|
var macroBody := tailNodes[2];
|
||||||
|
|
||||||
|
Result := TAst.MacroDef(macroName, macroParams, macroBody);
|
||||||
|
end
|
||||||
else if SameText(head.Token.Text, 'assign') then
|
else if SameText(head.Token.Text, 'assign') then
|
||||||
begin
|
begin
|
||||||
if tailTokens[0].Kind <> tkIdentifier then
|
if tailTokens[0].Kind <> tkIdentifier then
|
||||||
@@ -424,6 +439,19 @@ var
|
|||||||
i64: Int64;
|
i64: Int64;
|
||||||
dbl: Double;
|
dbl: Double;
|
||||||
begin
|
begin
|
||||||
|
// TODO: Implement reader macros for quasiquoting here.
|
||||||
|
// The current lexer will tokenize `, ~, and ~@ as identifiers.
|
||||||
|
// Check for them here and wrap the subsequent expression accordingly.
|
||||||
|
// Example:
|
||||||
|
// if FCurrentToken.Text = '`' then
|
||||||
|
// begin
|
||||||
|
// NextToken;
|
||||||
|
// var exprToQuote := ParseExpression;
|
||||||
|
// Result.Node := TAst.Quasiquote(exprToQuote.Node);
|
||||||
|
// exit;
|
||||||
|
// end;
|
||||||
|
// (This requires IQuasiquoteNode and TAst.Quasiquote to be defined first).
|
||||||
|
|
||||||
Result.Token := FCurrentToken;
|
Result.Token := FCurrentToken;
|
||||||
case FCurrentToken.Kind of
|
case FCurrentToken.Kind of
|
||||||
tkNumber:
|
tkNumber:
|
||||||
@@ -606,6 +634,33 @@ begin
|
|||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPrettyPrintVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
|
var
|
||||||
|
param: IIdentifierNode;
|
||||||
|
sb: TStringBuilder;
|
||||||
|
begin
|
||||||
|
// Added visitor for pretty printing macro definitions.
|
||||||
|
sb := TStringBuilder.Create;
|
||||||
|
try
|
||||||
|
for param in Node.Parameters do
|
||||||
|
sb.Append(param.Name + ' ');
|
||||||
|
if sb.Length > 0 then
|
||||||
|
sb.Remove(sb.Length - 1, 1);
|
||||||
|
|
||||||
|
Append('(defmacro ' + Node.Name.Name + ' [' + sb.ToString + ']');
|
||||||
|
finally
|
||||||
|
sb.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Indent;
|
||||||
|
NewLine;
|
||||||
|
Node.Body.Accept(Self);
|
||||||
|
Unindent;
|
||||||
|
NewLine;
|
||||||
|
Append(')');
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
function TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||||
var
|
var
|
||||||
arg: IAstNode;
|
arg: IAstNode;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ type
|
|||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; virtual; abstract;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; virtual; abstract;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; virtual; abstract;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; virtual; abstract;
|
||||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue; virtual; abstract;
|
function VisitAssignment(const Node: IAssignmentNode): TDataValue; virtual; abstract;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; virtual; abstract;
|
||||||
function VisitIndexer(const Node: IIndexerNode): TDataValue; virtual; abstract;
|
function VisitIndexer(const Node: IIndexerNode): TDataValue; virtual; abstract;
|
||||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; virtual; abstract;
|
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; virtual; abstract;
|
||||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; virtual; abstract;
|
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; virtual; abstract;
|
||||||
@@ -57,6 +58,7 @@ type
|
|||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override; final;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override; final;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override; final;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override; final;
|
||||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override; final;
|
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override; final;
|
||||||
|
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override; final;
|
||||||
function VisitIndexer(const Node: IIndexerNode): TDataValue; override; final;
|
function VisitIndexer(const Node: IIndexerNode): TDataValue; override; final;
|
||||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override; final;
|
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override; final;
|
||||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override; final;
|
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override; final;
|
||||||
@@ -76,6 +78,7 @@ type
|
|||||||
function TransformBlockExpression(const Node: IBlockExpressionNode): IBlockExpressionNode; virtual;
|
function TransformBlockExpression(const Node: IBlockExpressionNode): IBlockExpressionNode; virtual;
|
||||||
function TransformVariableDeclaration(const Node: IVariableDeclarationNode): IVariableDeclarationNode; virtual;
|
function TransformVariableDeclaration(const Node: IVariableDeclarationNode): IVariableDeclarationNode; virtual;
|
||||||
function TransformAssignment(const Node: IAssignmentNode): IAssignmentNode; virtual;
|
function TransformAssignment(const Node: IAssignmentNode): IAssignmentNode; virtual;
|
||||||
|
function TransformMacroDefinition(const Node: IMacroDefinitionNode): IMacroDefinitionNode; virtual;
|
||||||
function TransformIndexer(const Node: IIndexerNode): IIndexerNode; virtual;
|
function TransformIndexer(const Node: IIndexerNode): IIndexerNode; virtual;
|
||||||
function TransformMemberAccess(const Node: IMemberAccessNode): IMemberAccessNode; virtual;
|
function TransformMemberAccess(const Node: IMemberAccessNode): IMemberAccessNode; virtual;
|
||||||
function TransformCreateSeries(const Node: ICreateSeriesNode): ICreateSeriesNode; virtual;
|
function TransformCreateSeries(const Node: ICreateSeriesNode): ICreateSeriesNode; virtual;
|
||||||
@@ -234,6 +237,18 @@ begin
|
|||||||
Result := TAst.Assign(identifier, value);
|
Result := TAst.Assign(identifier, value);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstTransformer.TransformMacroDefinition(const Node: IMacroDefinitionNode): IMacroDefinitionNode;
|
||||||
|
begin
|
||||||
|
// Added identity transform for macro definitions.
|
||||||
|
var name := Accept(Node.Name).AsIntf<IIdentifierNode>;
|
||||||
|
var parameters := TransformNodes<IIdentifierNode>(Node.Parameters);
|
||||||
|
var body := Accept(Node.Body).AsIntf<IAstNode>;
|
||||||
|
if (name = Node.Name) and (parameters = Node.Parameters) and (body = Node.Body) then
|
||||||
|
Result := Node
|
||||||
|
else
|
||||||
|
Result := TAst.MacroDef(name, parameters, body);
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstTransformer.TransformIndexer(const Node: IIndexerNode): IIndexerNode;
|
function TAstTransformer.TransformIndexer(const Node: IIndexerNode): IIndexerNode;
|
||||||
begin
|
begin
|
||||||
var base := Accept(Node.Base).AsIntf<IAstNode>;
|
var base := Accept(Node.Base).AsIntf<IAstNode>;
|
||||||
@@ -360,6 +375,12 @@ begin
|
|||||||
Result := TDataValue.FromIntf<IAssignmentNode>(TransformAssignment(Node));
|
Result := TDataValue.FromIntf<IAssignmentNode>(TransformAssignment(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstTransformer.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
|
begin
|
||||||
|
// Added visit method for macro definitions.
|
||||||
|
Result := TDataValue.FromIntf<IMacroDefinitionNode>(TransformMacroDefinition(Node));
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
function TAstTransformer.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromIntf<IIndexerNode>(TransformIndexer(Node));
|
Result := TDataValue.FromIntf<IIndexerNode>(TransformIndexer(Node));
|
||||||
|
|||||||
+64
-5
@@ -36,6 +36,11 @@ type
|
|||||||
class function IfExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): IIfExpressionNode; static;
|
class function IfExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): IIfExpressionNode; static;
|
||||||
class function TernaryExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): ITernaryExpressionNode; static;
|
class function TernaryExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): ITernaryExpressionNode; static;
|
||||||
class function LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode; static;
|
class function LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode; static;
|
||||||
|
class function MacroDef(
|
||||||
|
const AName: IIdentifierNode;
|
||||||
|
const AParameters: TArray<IIdentifierNode>;
|
||||||
|
const ABody: IAstNode
|
||||||
|
): IMacroDefinitionNode; static;
|
||||||
class function FunctionCall(const ACallee: IAstNode; const AArguments: TArray<IAstNode>): IFunctionCallNode; static;
|
class function FunctionCall(const ACallee: IAstNode; const AArguments: TArray<IAstNode>): IFunctionCallNode; static;
|
||||||
class function Recur(const AArguments: array of IAstNode): IRecurNode; static;
|
class function Recur(const AArguments: array of IAstNode): IRecurNode; static;
|
||||||
class function Block(const AExpressions: array of IAstNode): IBlockExpressionNode; static;
|
class function Block(const AExpressions: array of IAstNode): IBlockExpressionNode; static;
|
||||||
@@ -141,6 +146,19 @@ type
|
|||||||
property Parameters: TArray<IIdentifierNode> read FParameters;
|
property Parameters: TArray<IIdentifierNode> read FParameters;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TMacroDefinitionNode = class(TAstNode, IMacroDefinitionNode)
|
||||||
|
private
|
||||||
|
FName: IIdentifierNode;
|
||||||
|
FParameters: TArray<IIdentifierNode>;
|
||||||
|
FBody: IAstNode;
|
||||||
|
function GetName: IIdentifierNode;
|
||||||
|
function GetParameters: TArray<IIdentifierNode>;
|
||||||
|
function GetBody: IAstNode;
|
||||||
|
public
|
||||||
|
constructor Create(const AName: IIdentifierNode; const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
|
||||||
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
|
end;
|
||||||
|
|
||||||
TFunctionCallNode = class(TAstNode, IFunctionCallNode)
|
TFunctionCallNode = class(TAstNode, IFunctionCallNode)
|
||||||
private
|
private
|
||||||
FCallee: IAstNode;
|
FCallee: IAstNode;
|
||||||
@@ -428,6 +446,37 @@ begin
|
|||||||
Result := FParameters;
|
Result := FParameters;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TMacroDefinitionNode }
|
||||||
|
|
||||||
|
constructor TMacroDefinitionNode.Create(const AName: IIdentifierNode; const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
|
||||||
|
begin
|
||||||
|
// Added concrete class for macro definitions.
|
||||||
|
inherited Create;
|
||||||
|
FName := AName;
|
||||||
|
FParameters := AParameters;
|
||||||
|
FBody := ABody;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMacroDefinitionNode.Accept(const Visitor: IAstVisitor): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := Visitor.VisitMacroDefinition(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMacroDefinitionNode.GetBody: IAstNode;
|
||||||
|
begin
|
||||||
|
Result := FBody;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMacroDefinitionNode.GetName: IIdentifierNode;
|
||||||
|
begin
|
||||||
|
Result := FName;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMacroDefinitionNode.GetParameters: TArray<IIdentifierNode>;
|
||||||
|
begin
|
||||||
|
Result := FParameters;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TFunctionCallNode }
|
{ TFunctionCallNode }
|
||||||
|
|
||||||
constructor TFunctionCallNode.Create(const ACallee: IAstNode; const AArguments: TArray<IAstNode>);
|
constructor TFunctionCallNode.Create(const ACallee: IAstNode; const AArguments: TArray<IAstNode>);
|
||||||
@@ -751,6 +800,21 @@ begin
|
|||||||
Result := TIndexerNode.Create(ABase, AIndex);
|
Result := TIndexerNode.Create(ABase, AIndex);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TAst.LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode;
|
||||||
|
begin
|
||||||
|
Result := TLambdaExpressionNode.Create(AParameters, ABody);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TAst.MacroDef(
|
||||||
|
const AName: IIdentifierNode;
|
||||||
|
const AParameters: TArray<IIdentifierNode>;
|
||||||
|
const ABody: IAstNode
|
||||||
|
): IMacroDefinitionNode;
|
||||||
|
begin
|
||||||
|
// Added factory for macro definitions.
|
||||||
|
Result := TMacroDefinitionNode.Create(AName, AParameters, ABody);
|
||||||
|
end;
|
||||||
|
|
||||||
class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IIdentifierNode): IMemberAccessNode;
|
class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IIdentifierNode): IMemberAccessNode;
|
||||||
begin
|
begin
|
||||||
Result := TMemberAccessNode.Create(ABase, AMember);
|
Result := TMemberAccessNode.Create(ABase, AMember);
|
||||||
@@ -777,11 +841,6 @@ begin
|
|||||||
Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch);
|
Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode;
|
|
||||||
begin
|
|
||||||
Result := TLambdaExpressionNode.Create(AParameters, ABody);
|
|
||||||
end;
|
|
||||||
|
|
||||||
class function TAst.UnaryExpr(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode): IUnaryExpressionNode;
|
class function TAst.UnaryExpr(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode): IUnaryExpressionNode;
|
||||||
begin
|
begin
|
||||||
Result := TUnaryExpressionNode.Create(AOperator, ARight);
|
Result := TUnaryExpressionNode.Create(AOperator, ARight);
|
||||||
|
|||||||
Reference in New Issue
Block a user