1 /**
2  * Provides an AST printer for debugging.
3  *
4  * Copyright:   Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
5  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
6  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/printast.d, _printast.d)
8  * Documentation:  https://dlang.org/phobos/dmd_printast.html
9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/printast.d
10  */
11 
12 module dmd.printast;
13 
14 import core.stdc.stdio;
15 
16 import dmd.expression;
17 import dmd.ctfeexpr;
18 import dmd.tokens;
19 import dmd.visitor;
20 import dmd.hdrgen;
21 
22 /********************
23  * Print AST data structure in a nice format.
24  * Params:
25  *  e = expression AST to print
26  *  indent = indentation level
27  */
28 void printAST(Expression e, int indent = 0)
29 {
30     scope PrintASTVisitor pav = new PrintASTVisitor(indent);
31     e.accept(pav);
32 }
33 
34 private:
35 
36 extern (C++) final class PrintASTVisitor : Visitor
37 {
38     alias visit = Visitor.visit;
39 
40     int indent;
41 
42     extern (D) this(int indent) scope @safe
43     {
44         this.indent = indent;
45     }
46 
47     override void visit(Expression e)
48     {
49         printIndent(indent);
50         auto s = EXPtoString(e.op);
51         printf("%.*s %s\n", cast(int)s.length, s.ptr, e.type ? e.type.toChars() : "");
52     }
53 
54     override void visit(IntegerExp e)
55     {
56         printIndent(indent);
57         printf("Integer %lld %s\n", e.toInteger(), e.type ? e.type.toChars() : "");
58     }
59 
60     override void visit(RealExp e)
61     {
62         printIndent(indent);
63 
64         import dmd.hdrgen : floatToBuffer;
65         import dmd.common.outbuffer : OutBuffer;
66         OutBuffer buf;
67         floatToBuffer(e.type, e.value, buf, false);
68         printf("Real %s %s\n", buf.peekChars(), e.type ? e.type.toChars() : "");
69     }
70 
71     override void visit(StructLiteralExp e)
72     {
73         printIndent(indent);
74         auto s = EXPtoString(e.op);
75         printf("%.*s %s, %s\n", cast(int)s.length, s.ptr, e.type ? e.type.toChars() : "", e.toChars());
76     }
77 
78     override void visit(SymbolExp e)
79     {
80         printIndent(indent);
81         printf("Symbol %s\n", e.type ? e.type.toChars() : "");
82         printIndent(indent + 2);
83         printf(".var: %s\n", e.var ? e.var.toChars() : "");
84     }
85 
86     override void visit(SymOffExp e)
87     {
88         printIndent(indent);
89         printf("SymOff %s\n", e.type ? e.type.toChars() : "");
90         printIndent(indent + 2);
91         printf(".var: %s\n", e.var ? e.var.toChars() : "");
92         printIndent(indent + 2);
93         printf(".offset: %llx\n", e.offset);
94     }
95 
96     override void visit(VarExp e)
97     {
98         printIndent(indent);
99         printf("Var %s\n", e.type ? e.type.toChars() : "");
100         printIndent(indent + 2);
101         printf(".var: %s\n", e.var ? e.var.toChars() : "");
102     }
103 
104     override void visit(DsymbolExp e)
105     {
106         visit(cast(Expression)e);
107         printIndent(indent + 2);
108         printf(".s: %s\n", e.s ? e.s.toChars() : "");
109     }
110 
111     override void visit(DotIdExp e)
112     {
113         printIndent(indent);
114         printf("DotId %s\n", e.type ? e.type.toChars() : "");
115         printIndent(indent + 2);
116         printf(".ident: %s\n", e.ident.toChars());
117         printAST(e.e1, indent + 2);
118     }
119 
120     override void visit(UnaExp e)
121     {
122         visit(cast(Expression)e);
123         printAST(e.e1, indent + 2);
124     }
125 
126     override void visit(CastExp e)
127     {
128         printIndent(indent);
129         auto s = EXPtoString(e.op);
130         printf("%.*s %s\n", cast(int)s.length, s.ptr, e.type ? e.type.toChars() : "");
131         printIndent(indent + 2);
132         printf(".to: %s\n", e.to.toChars());
133         printAST(e.e1, indent + 2);
134     }
135 
136     override void visit(VectorExp e)
137     {
138         printIndent(indent);
139         printf("Vector %s\n", e.type ? e.type.toChars() : "");
140         printIndent(indent + 2);
141         printf(".to: %s\n", e.to.toChars());
142         printAST(e.e1, indent + 2);
143     }
144 
145     override void visit(VectorArrayExp e)
146     {
147         printIndent(indent);
148         printf("VectorArray %s\n", e.type ? e.type.toChars() : "");
149         printAST(e.e1, indent + 2);
150     }
151 
152     override void visit(DotVarExp e)
153     {
154         printIndent(indent);
155         printf("DotVar %s\n", e.type ? e.type.toChars() : "");
156         printIndent(indent + 2);
157         printf(".var: %s\n", e.var.toChars());
158         printAST(e.e1, indent + 2);
159     }
160 
161     override void visit(BinExp e)
162     {
163         visit(cast(Expression)e);
164         printAST(e.e1, indent + 2);
165         printAST(e.e2, indent + 2);
166     }
167 
168     override void visit(AssignExp e)
169     {
170         printIndent(indent);
171         printf("Assign %s\n", e.type ? e.type.toChars() : "");
172         printAST(e.e1, indent + 2);
173         printAST(e.e2, indent + 2);
174     }
175 
176     override void visit(ConstructExp e)
177     {
178         printIndent(indent);
179         printf("Construct %s\n", e.type ? e.type.toChars() : "");
180         printAST(e.e1, indent + 2);
181         printAST(e.e2, indent + 2);
182     }
183 
184     override void visit(BlitExp e)
185     {
186         printIndent(indent);
187         printf("Blit %s\n", e.type ? e.type.toChars() : "");
188         printAST(e.e1, indent + 2);
189         printAST(e.e2, indent + 2);
190     }
191 
192     override void visit(IndexExp e)
193     {
194         printIndent(indent);
195         printf("Index %s\n", e.type ? e.type.toChars() : "");
196         printAST(e.e1, indent + 2);
197         printAST(e.e2, indent + 2);
198     }
199 
200     override void visit(DelegateExp e)
201     {
202         visit(cast(Expression)e);
203         printIndent(indent + 2);
204         printf(".func: %s\n", e.func ? e.func.toChars() : "");
205     }
206 
207     override void visit(CompoundLiteralExp e)
208     {
209         visit(cast(Expression)e);
210         printIndent(indent + 2);
211         printf(".init: %s\n", e.initializer ? e.initializer.toChars() : "");
212     }
213 
214     override void visit(ClassReferenceExp e)
215     {
216         visit(cast(Expression)e);
217         printIndent(indent + 2);
218         printf(".value: %s\n", e.value ? e.value.toChars() : "");
219         printAST(e.value, indent + 2);
220     }
221 
222     override void visit(ArrayLiteralExp e)
223     {
224         visit(cast(Expression)e);
225         printIndent(indent + 2);
226         printf(".basis : %s\n", e.basis ? e.basis.toChars() : "");
227         if (e.elements)
228         {
229             printIndent(indent + 2);
230             printf("[");
231             foreach (i, element; (*e.elements)[])
232             {
233                 if (i)
234                     printf(", ");
235                 printf("%s", element.toChars());
236             }
237             printf("]\n");
238         }
239     }
240 
241     static void printIndent(int indent)
242     {
243         foreach (i; 0 .. indent)
244             putc(' ', stdout);
245     }
246 }