Generic Visitors

This commit is contained in:
Michael Schimmel
2026-01-03 19:14:18 +01:00
parent db74b83e11
commit 22674b962b
27 changed files with 3573 additions and 3547 deletions
+2 -408
View File
@@ -6,7 +6,8 @@ uses
System.SysUtils,
Myc.Data.Value,
Myc.Ast.Nodes,
Myc.Ast.Visitor;
Myc.Ast.Visitor,
Myc.Ast.Script.Print;
type
EParserException = class(EAstException)
@@ -116,57 +117,6 @@ type
function Parse: IAstNode;
end;
TPrettyPrintVisitor = class(TAstVisitor)
private
FBuilder: TStringBuilder;
FIndentLevel: Integer;
procedure Indent;
procedure Unindent;
procedure Append(const S: string);
procedure NewLine;
public
constructor Create;
destructor Destroy; override;
function GetResult: string;
function Execute(const RootNode: IAstNode): TDataValue;
function VisitConstant(const Node: IConstantNode): TVoid; override;
function VisitIdentifier(const Node: IIdentifierNode): TVoid; override;
function VisitKeyword(const Node: IKeywordNode): TVoid; override;
function VisitParameterList(const Node: IParameterList): TVoid; override;
function VisitArgumentList(const Node: IArgumentList): TVoid; override;
function VisitExpressionList(const Node: IExpressionList): TVoid; override;
function VisitRecordFieldList(const Node: IRecordFieldList): TVoid; override;
function VisitRecordField(const Node: IRecordFieldNode): TVoid; override;
function VisitIfExpression(const Node: IIfExpressionNode): TVoid; override;
function VisitCondExpression(const Node: ICondExpressionNode): TVoid; override;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TVoid; override;
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TVoid; override;
function VisitQuasiquote(const Node: IQuasiquoteNode): TVoid; override;
function VisitUnquote(const Node: IUnquoteNode): TVoid; override;
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TVoid; override;
function VisitFunctionCall(const Node: IFunctionCallNode): TVoid; override;
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TVoid; override;
function VisitBlockExpression(const Node: IBlockExpressionNode): TVoid; override;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TVoid; override;
function VisitAssignment(const Node: IAssignmentNode): TVoid; override;
function VisitIndexer(const Node: IIndexerNode): TVoid; override;
function VisitMemberAccess(const Node: IMemberAccessNode): TVoid; override;
function VisitRecordLiteral(const Node: IRecordLiteralNode): TVoid; override;
function VisitCreateSeries(const Node: ICreateSeriesNode): TVoid; override;
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TVoid; override;
function VisitSeriesLength(const Node: ISeriesLengthNode): TVoid; override;
function VisitRecurNode(const Node: IRecurNode): TVoid; override;
function VisitNop(const Node: INopNode): TVoid; override;
function VisitPipeInput(const Node: IPipeInputNode): TVoid; override;
function VisitPipeSelectorList(const Node: IPipeSelectorList): TVoid; override;
function VisitPipeInputList(const Node: IPipeInputList): TVoid; override;
function VisitPipe(const Node: IPipeNode): TVoid; override;
end;
{ TTokenKindHelper }
function TTokenKindHelper.ToString: String;
begin
@@ -812,362 +762,6 @@ begin
Result := expr.Node;
end;
{ TPrettyPrintVisitor }
constructor TPrettyPrintVisitor.Create;
begin
inherited Create;
FBuilder := TStringBuilder.Create;
FIndentLevel := 0;
end;
destructor TPrettyPrintVisitor.Destroy;
begin
FBuilder.Free;
inherited;
end;
function TPrettyPrintVisitor.GetResult: string;
begin
Result := FBuilder.ToString;
end;
procedure TPrettyPrintVisitor.Indent;
begin
Inc(FIndentLevel, 2);
end;
procedure TPrettyPrintVisitor.Unindent;
begin
Dec(FIndentLevel, 2);
end;
procedure TPrettyPrintVisitor.Append(const S: string);
begin
FBuilder.Append(S);
end;
procedure TPrettyPrintVisitor.NewLine;
begin
FBuilder.AppendLine;
FBuilder.Append(''.PadLeft(FIndentLevel));
end;
function TPrettyPrintVisitor.Execute(const RootNode: IAstNode): TDataValue;
begin
if Assigned(RootNode) then
RootNode.Accept(Self);
Result := TDataValue.Void;
end;
function TPrettyPrintVisitor.VisitPipeInput(const Node: IPipeInputNode): TVoid;
begin
Node.StreamSource.Accept(Self);
Append(' ');
// Printer Logic for Vector syntax
Node.Selectors.Accept(Self); // Selectors is IPipeSelectorList which is visited as list
end;
function TPrettyPrintVisitor.VisitPipeSelectorList(const Node: IPipeSelectorList): TVoid;
begin
Append('[');
for var i := 0 to Node.Count - 1 do
begin
if i > 0 then
Append(' ');
Node[i].Accept(Self);
end;
Append(']');
end;
function TPrettyPrintVisitor.VisitPipeInputList(const Node: IPipeInputList): TVoid;
begin
Append('[');
for var i := 0 to Node.Count - 1 do
begin
if i > 0 then
Append(' ');
Node[i].Accept(Self);
end;
Append(']');
end;
function TPrettyPrintVisitor.VisitPipe(const Node: IPipeNode): TVoid;
begin
Append('(pipe ');
Node.Inputs.Accept(Self);
Indent;
NewLine;
Node.Transformation.Accept(Self);
Unindent;
NewLine;
Append(')');
end;
function TPrettyPrintVisitor.VisitConstant(const Node: IConstantNode): TVoid;
begin
if Node.Value.Kind = vkText then
Append('"' + Node.Value.AsText + '"')
else
Append(Node.Value.ToString);
end;
function TPrettyPrintVisitor.VisitIdentifier(const Node: IIdentifierNode): TVoid;
begin
Append(Node.Name);
end;
function TPrettyPrintVisitor.VisitKeyword(const Node: IKeywordNode): TVoid;
begin
Append(':' + Node.Value.Name);
end;
function TPrettyPrintVisitor.VisitNop(const Node: INopNode): TVoid;
begin
Append('...');
end;
function TPrettyPrintVisitor.VisitParameterList(const Node: IParameterList): TVoid;
begin
Append('[');
for var i := 0 to Node.Count - 1 do
begin
if i > 0 then
Append(' ');
Node[i].Accept(Self);
end;
Append(']');
end;
function TPrettyPrintVisitor.VisitArgumentList(const Node: IArgumentList): TVoid;
begin
for var i := 0 to Node.Count - 1 do
begin
Append(' ');
Node[i].Accept(Self);
end;
end;
function TPrettyPrintVisitor.VisitExpressionList(const Node: IExpressionList): TVoid;
begin
Indent;
for var item in Node do
begin
NewLine;
item.Accept(Self);
end;
Unindent;
NewLine;
end;
function TPrettyPrintVisitor.VisitRecordFieldList(const Node: IRecordFieldList): TVoid;
begin
Indent;
for var item in Node do
begin
NewLine;
item.Accept(Self);
end;
Unindent;
NewLine;
end;
function TPrettyPrintVisitor.VisitRecordField(const Node: IRecordFieldNode): TVoid;
begin
Node.Key.Accept(Self);
Append(' ');
Node.Value.Accept(Self);
end;
function TPrettyPrintVisitor.VisitIfExpression(const Node: IIfExpressionNode): TVoid;
begin
Append('(if ');
Node.Condition.Accept(Self);
Indent;
NewLine;
Node.ThenBranch.Accept(Self);
if Assigned(Node.ElseBranch) then
begin
NewLine;
Node.ElseBranch.Accept(Self);
end;
Unindent;
NewLine;
Append(')');
end;
function TPrettyPrintVisitor.VisitCondExpression(const Node: ICondExpressionNode): TVoid;
begin
Append('(?');
Indent;
for var pair in Node.Pairs do
begin
NewLine;
pair.Condition.Accept(Self);
Append(' ');
pair.Branch.Accept(Self);
end;
NewLine;
Node.ElseBranch.Accept(Self);
Unindent;
NewLine;
Append(')');
end;
function TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TVoid;
begin
Append('(fn ');
Node.Parameters.Accept(Self);
Indent;
NewLine;
Node.Body.Accept(Self);
Unindent;
NewLine;
Append(')');
end;
function TPrettyPrintVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TVoid;
begin
Append('(defmacro ');
Node.Name.Accept(Self);
Append(' ');
Node.Parameters.Accept(Self);
Indent;
NewLine;
Node.Body.Accept(Self);
Unindent;
NewLine;
Append(')');
end;
function TPrettyPrintVisitor.VisitQuasiquote(const Node: IQuasiquoteNode): TVoid;
begin
Append('`');
Node.Expression.Accept(Self);
end;
function TPrettyPrintVisitor.VisitUnquote(const Node: IUnquoteNode): TVoid;
begin
Append('~');
Node.Expression.Accept(Self);
end;
function TPrettyPrintVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TVoid;
begin
Append('~@');
Node.Expression.Accept(Self);
end;
function TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TVoid;
begin
if (Node.Callee.Kind = akIdentifier) and (Node.Callee.AsIdentifier.Name = 'quote') and (Node.Arguments.Count = 1) then
begin
Append('''');
Node.Arguments[0].Accept(Self);
exit;
end;
Append('(');
Node.Callee.Accept(Self);
Node.Arguments.Accept(Self);
Append(')');
end;
function TPrettyPrintVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TVoid;
begin
VisitFunctionCall(Node.CallNode);
end;
function TPrettyPrintVisitor.VisitRecurNode(const Node: IRecurNode): TVoid;
begin
Append('(recur');
Node.Arguments.Accept(Self);
Append(')');
end;
function TPrettyPrintVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TVoid;
begin
Append('(do');
Node.Expressions.Accept(Self);
Append(')');
end;
function TPrettyPrintVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TVoid;
begin
Append('(def ');
Node.Target.Accept(Self);
if Assigned(Node.Initializer) then
begin
Append(' ');
Node.Initializer.Accept(Self);
end;
Append(')');
end;
function TPrettyPrintVisitor.VisitAssignment(const Node: IAssignmentNode): TVoid;
begin
Append('(assign ');
Node.Target.Accept(Self);
Append(' ');
Node.Value.Accept(Self);
Append(')');
end;
function TPrettyPrintVisitor.VisitIndexer(const Node: IIndexerNode): TVoid;
begin
Append('(get ');
Node.Base.Accept(Self);
Append(' ');
Node.Index.Accept(Self);
Append(')');
end;
function TPrettyPrintVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TVoid;
begin
Append('(.');
Node.Member.Accept(Self);
Append(' ');
Node.Base.Accept(Self);
Append(')');
end;
function TPrettyPrintVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode): TVoid;
begin
if Node.Fields.Count = 0 then
begin
Append('{}');
exit;
end;
Append('{');
Node.Fields.Accept(Self);
Append('}');
end;
function TPrettyPrintVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TVoid;
begin
Append(Format('(new-series "%s")', [Node.Definition]));
end;
function TPrettyPrintVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TVoid;
begin
Append('(add-item ');
Node.Series.Accept(Self);
Append(' ');
Node.Value.Accept(Self);
if Assigned(Node.Lookback) then
begin
Append(' ');
Node.Lookback.Accept(Self);
end;
Append(')');
end;
function TPrettyPrintVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TVoid;
begin
Append('(count ');
Node.Series.Accept(Self);
Append(')');
end;
{ TAstScript }
class function TAstScript.Parse(const ASource: string): IAstNode;