]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/debug.cpp
Refactor interface management
[libs/gl.git] / source / glsl / debug.cpp
1 #include <msp/stringcodec/utf8.h>
2 #include <msp/strings/format.h>
3 #include "debug.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9 namespace SL {
10
11 const std::string &DumpTree::apply(Stage &stage)
12 {
13         formatted = format("Stage %s\n", Stage::get_stage_name(stage.type));
14         tree.push_back(BRANCH);
15         last_branch();
16         stage.content.visit(*this);
17         return formatted;
18 }
19
20 void DumpTree::append(const string &line)
21 {
22         StringCodec::Utf8::Encoder enc;
23         for(vector<TreeChars>::const_iterator i=tree.begin(); i!=tree.end(); )
24         {
25                 enc.encode_char(*i++, formatted);
26                 enc.encode_char((i==tree.end() ? REACH : EMPTY), formatted);
27         }
28         formatted += line;
29         formatted += '\n';
30 }
31
32 void DumpTree::begin_sub()
33 {
34         tree.back() = (tree.back()==BRANCH_LAST ? EMPTY : STRAIGHT);
35         tree.push_back(BRANCH);
36 }
37
38 void DumpTree::last_branch()
39 {
40         tree.back() = BRANCH_LAST;
41 }
42
43 void DumpTree::end_sub()
44 {
45         tree.pop_back();
46         if(tree.back()==STRAIGHT)
47                 tree.back() = BRANCH;
48 }
49
50 void DumpTree::annotated_branch(const string &annotation, Node &node)
51 {
52         append(annotation);
53         begin_sub();
54         last_branch();
55         node.visit(*this);
56         end_sub();
57 }
58
59 unsigned DumpTree::get_label(const Node &node)
60 {
61         unsigned &label = node_labels[&node];
62         if(!label)
63                 label = node_labels.size();
64         return label;
65 }
66
67 template<typename T>
68 typename T::const_iterator DumpTree::increment(typename T::const_iterator &iter, const T &container)
69 {
70         typename T::const_iterator ret = iter++;
71         if(iter==container.end())
72                 last_branch();
73         return ret;
74 }
75
76 void DumpTree::visit(Block &block)
77 {
78         append(format("Block %s", (block.use_braces ? "{}" : "(inline)")));
79         begin_sub();
80
81         for(std::map<string, StructDeclaration *>::const_iterator i=block.types.begin(); i!=block.types.end(); ++i)
82                 append(format("Type %%%d %s", get_label(*i->second), i->first));
83
84         for(std::map<string, VariableDeclaration *>::const_iterator i=block.variables.begin(); i!=block.variables.end(); ++i)
85                 append(format("Variable %%%d %s %s", get_label(*i->second), i->second->type, i->first));
86
87         for(std::set<InterfaceBlock *>::const_iterator i=block.interfaces.begin(); i!=block.interfaces.end(); ++i)
88                 append(format("Interface %%%d %s %s", get_label(*i->second), i->second->interface, i->second->name));
89
90         bool labeled_body = (!block.types.empty() || !block.variables.empty());
91         if(labeled_body)
92         {
93                 last_branch();
94                 append("Body");
95                 begin_sub();
96         }
97         for(NodeList<Statement>::const_iterator i=block.body.begin(); i!=block.body.end(); )
98         {
99                 NodeList<Statement>::const_iterator j = increment(i, block.body);
100                 (*j)->visit(*this);
101         }
102         if(labeled_body)
103                 end_sub();
104
105         end_sub();
106 }
107
108 void DumpTree::visit(Literal &literal)
109 {
110         append(format("Literal: %s", literal.token));
111 }
112
113 void DumpTree::visit(ParenthesizedExpression &parexpr)
114 {
115         annotated_branch("(expr)", *parexpr.expression);
116 }
117
118 void DumpTree::visit(VariableReference &var)
119 {
120         string text;
121         if(var.declaration)
122                 text += format("%%%d ", get_label(*var.declaration));
123         text += var.name;
124         append(text);
125 }
126
127 void DumpTree::visit(MemberAccess &memacc)
128 {
129         string text = "Member access:";
130         if(memacc.declaration)
131                 text += format(" %%%d", get_label(*memacc.declaration));
132         text += format(" .%s", memacc.member);
133         annotated_branch(text, *memacc.left);
134 }
135
136 void DumpTree::visit(UnaryExpression &unary)
137 {
138         annotated_branch(format("Unary: %s, %sfix", unary.oper, (unary.prefix ? "pre" : "suff")), *unary.expression);
139 }
140
141 void DumpTree::visit(BinaryExpression &binary)
142 {
143         append(format("Binary: %s%s", binary.oper, binary.after));
144         begin_sub();
145         binary.left->visit(*this);
146         last_branch();
147         binary.right->visit(*this);
148         end_sub();
149 }
150
151 void DumpTree::visit(Assignment &assign)
152 {
153         append(format("Assignment: %s%s", assign.oper, (assign.self_referencing ? " (self-referencing)" : "")));
154         begin_sub();
155         assign.left->visit(*this);
156         last_branch();
157         assign.right->visit(*this);
158         end_sub();
159 }
160
161 void DumpTree::visit(FunctionCall &call)
162 {
163         string head = "Function call: ";
164         if(call.declaration)
165                 head += format("%%%d ", get_label(*call.declaration));
166         head += call.name;
167         if(call.constructor)
168                 head += " (constructor)";
169         append(head);
170
171         begin_sub();
172         for(NodeArray<Expression>::const_iterator i=call.arguments.begin(); i!=call.arguments.end(); )
173         {
174                 NodeArray<Expression>::const_iterator j = increment(i, call.arguments);
175                 (*j)->visit(*this);
176         }
177         end_sub();
178 }
179
180 void DumpTree::visit(ExpressionStatement &expr)
181 {
182         annotated_branch("expr;", *expr.expression);
183 }
184
185 void DumpTree::visit(Import &import)
186 {
187         append(format("import %s", import.module));
188 }
189
190 void DumpTree::visit(Precision &prec)
191 {
192         append(format("precision %s %s", prec.precision, prec.type));
193 }
194
195 void DumpTree::visit(Layout &layout)
196 {
197         append("Layout");
198         begin_sub();
199         for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); )
200         {
201                 vector<Layout::Qualifier>::const_iterator j = increment(i, layout.qualifiers);
202                 string qualifier = j->name;
203                 if(j->has_value)
204                         qualifier += format("=%d", j->value);
205                 append(qualifier);
206         }
207         end_sub();
208 }
209
210 void DumpTree::visit(InterfaceLayout &layout)
211 {
212         annotated_branch(format("Layout: %s", layout.interface), layout.layout);
213 }
214
215 void DumpTree::visit(StructDeclaration &strct)
216 {
217         annotated_branch(format("%%%d struct %s", get_label(strct), strct.name), strct.members);
218 }
219
220 void DumpTree::visit(VariableDeclaration &var)
221 {
222         string decl = format("%%%d ", get_label(var));
223         if(var.constant)
224                 decl += "const ";
225         if(!var.interpolation.empty())
226                 decl += format("%s ", var.interpolation);
227         if(!var.sampling.empty())
228                 decl += format("%s ", var.sampling);
229         if(!var.interface.empty())
230                 decl += format("%s ", var.interface);
231         if(!var.precision.empty())
232                 decl += format("%s ", var.precision);
233         decl += format("%s %s", var.type, var.name);
234         if(var.linked_declaration)
235                 decl += " (linked)";
236         append(decl);
237
238         begin_sub();
239         if(!var.array && !var.init_expression)
240                 last_branch();
241         if(var.layout)
242                 var.layout->visit(*this);
243
244         if(!var.init_expression)
245                 last_branch();
246         if(var.array)
247         {
248                 if(var.array_size)
249                         annotated_branch("Array []", *var.array_size);
250                 else
251                         append("Array []");
252         }
253
254         last_branch();
255         if(var.init_expression)
256                 var.init_expression->visit(*this);
257         end_sub();
258 }
259
260 void DumpTree::visit(InterfaceBlock &block)
261 {
262         annotated_branch(format("%s %s", block.interface, block.name), block.members);
263 }
264
265 void DumpTree::visit(FunctionDeclaration &func)
266 {
267         append(format("%%%d %s %s()", get_label(func), func.return_type, func.name));
268         begin_sub();
269         for(NodeArray<VariableDeclaration>::const_iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
270                 (*i)->visit(*this);
271         if(func.definition)
272                 append(format("Definition %%%d", get_label(*func.definition)));
273         last_branch();
274         func.body.visit(*this);
275         end_sub();
276 }
277
278 void DumpTree::visit(Conditional &cond)
279 {
280         append("if()");
281         begin_sub();
282         cond.condition->visit(*this);
283         if(cond.else_body.body.empty())
284                 last_branch();
285         cond.body.visit(*this);
286         if(!cond.else_body.body.empty())
287         {
288                 last_branch();
289                 cond.else_body.visit(*this);
290         }
291         end_sub();
292 }
293
294 void DumpTree::visit(Iteration &iter)
295 {
296         append("for()");
297         begin_sub();
298
299         if(iter.init_statement)
300                 annotated_branch("Initialization", *iter.init_statement);
301         if(iter.condition)
302                 annotated_branch("Condition", *iter.condition);
303         if(iter.loop_expression)
304                 annotated_branch("Loop", *iter.loop_expression);
305         last_branch();
306         annotated_branch("Body", iter.body);
307
308         end_sub();
309 }
310
311 void DumpTree::visit(Passthrough &pass)
312 {
313         append("passthrough");
314         if(pass.subscript)
315         {
316                 begin_sub();
317                 last_branch();
318                 pass.subscript->visit(*this);
319                 end_sub();
320         }
321 }
322
323 void DumpTree::visit(Return &ret)
324 {
325         if(ret.expression)
326                 annotated_branch("return", *ret.expression);
327         else
328                 append("return;");
329 }
330
331 void DumpTree::visit(Jump &jump)
332 {
333         append(format("%s;", jump.keyword));
334 }
335
336 } // namespace SL
337 } // namespace GL
338 } // namespace Msp