]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/visitor.cpp
dfe2d8d46523a00d83b024f1e13dc261db36703d
[libs/gl.git] / source / glsl / visitor.cpp
1 #include <msp/core/raii.h>
2 #include "visitor.h"
3
4 using namespace std;
5
6 namespace Msp {
7 namespace GL {
8 namespace SL {
9
10 void TraversingVisitor::visit(Block &block)
11 {
12         if(&block!=current_block)
13                 enter(block);
14         SetForScope<Block *> set_block(current_block, &block);
15         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
16                 (*i)->visit(*this);
17 }
18
19 void TraversingVisitor::visit(ParenthesizedExpression &parexpr)
20 {
21         parexpr.expression->visit(*this);
22 }
23
24 void TraversingVisitor::visit(MemberAccess &memacc)
25 {
26         memacc.left->visit(*this);
27 }
28
29 void TraversingVisitor::visit(Swizzle &swizzle)
30 {
31         swizzle.left->visit(*this);
32 }
33
34 void TraversingVisitor::visit(UnaryExpression &unary)
35 {
36         unary.expression->visit(*this);
37 }
38
39 void TraversingVisitor::visit(BinaryExpression &binary)
40 {
41         binary.left->visit(*this);
42         binary.right->visit(*this);
43 }
44
45 void TraversingVisitor::visit(Assignment &assign)
46 {
47         assign.left->visit(*this);
48         assign.right->visit(*this);
49 }
50
51 void TraversingVisitor::visit(FunctionCall &call)
52 {
53         for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
54                 (*i)->visit(*this);
55 }
56
57 void TraversingVisitor::visit(ExpressionStatement &expr)
58 {
59         expr.expression->visit(*this);
60 }
61
62 void TraversingVisitor::visit(InterfaceLayout &layout)
63 {
64         layout.layout.visit(*this);
65 }
66
67 void TraversingVisitor::visit(StructDeclaration &strct)
68 {
69         strct.members.visit(*this);
70 }
71
72 void TraversingVisitor::visit(VariableDeclaration &var)
73 {
74         if(var.layout)
75                 var.layout->visit(*this);
76         if(var.init_expression)
77                 var.init_expression->visit(*this);
78         if(var.array_size)
79                 var.array_size->visit(*this);
80 }
81
82 void TraversingVisitor::visit(InterfaceBlock &iface)
83 {
84         if(iface.members)
85                 iface.members->visit(*this);
86 }
87
88 void TraversingVisitor::visit(FunctionDeclaration &func)
89 {
90         enter(func.body);
91         SetForScope<Block *> set_block(current_block, &func.body);
92         for(NodeArray<VariableDeclaration>::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
93                 (*i)->visit(*this);
94         func.body.visit(*this);
95 }
96
97 void TraversingVisitor::visit(Conditional &cond)
98 {
99         cond.condition->visit(*this);
100         cond.body.visit(*this);
101         cond.else_body.visit(*this);
102 }
103
104 void TraversingVisitor::visit(Iteration &iter)
105 {
106         enter(iter.body);
107         SetForScope<Block *> set_block(current_block, &iter.body);
108         if(iter.init_statement)
109                 iter.init_statement->visit(*this);
110         if(iter.condition)
111                 iter.condition->visit(*this);
112         iter.body.visit(*this);
113         if(iter.loop_expression)
114                 iter.loop_expression->visit(*this);
115 }
116
117 void TraversingVisitor::visit(Passthrough &pass)
118 {
119         if(pass.subscript)
120                 pass.subscript->visit(*this);
121 }
122
123 void TraversingVisitor::visit(Return &ret)
124 {
125         if(ret.expression)
126                 ret.expression->visit(*this);
127 }
128
129
130 NodeRemover::NodeRemover():
131         stage(0),
132         to_remove(0),
133         recursive_remove(false)
134 { }
135
136 void NodeRemover::apply(Stage &s, const set<Node *> &tr)
137 {
138         stage = &s;
139         to_remove = &tr;
140         s.content.visit(*this);
141 }
142
143 template<typename T>
144 void NodeRemover::remove_from_map(map<string, T *> &vars, const string &key, T &node)
145 {
146         typename map<string, T *>::iterator i = vars.find(key);
147         if(i!=vars.end() && i->second==&node)
148                 vars.erase(i);
149 }
150
151 void NodeRemover::visit(Block &block)
152 {
153         SetForScope<Block *> set_block(current_block, &block);
154         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
155         {
156                 (*i)->visit(*this);
157                 if(to_remove->count(i->get()))
158                         block.body.erase(i++);
159                 else
160                         ++i;
161         }
162 }
163
164 void NodeRemover::visit(TypeDeclaration &type)
165 {
166         if(to_remove->count(&type))
167                 remove_from_map(stage->types, type.name, type);
168 }
169
170 void NodeRemover::visit(VariableDeclaration &var)
171 {
172         if(recursive_remove || to_remove->count(&var))
173         {
174                 remove_from_map(current_block->variables, var.name, var);
175                 stage->locations.erase(var.name);
176                 if(var.linked_declaration)
177                         var.linked_declaration->linked_declaration = 0;
178         }
179         else if(var.init_expression && to_remove->count(var.init_expression.get()))
180                 var.init_expression = 0;
181 }
182
183 void NodeRemover::visit(InterfaceBlock &iface)
184 {
185         if(to_remove->count(&iface))
186         {
187                 remove_from_map(stage->interface_blocks, iface.interface+iface.name, iface);
188                 if(!iface.instance_name.empty())
189                         remove_from_map(stage->interface_blocks, "_"+iface.instance_name, iface);
190         }
191         SetFlag set_recursive(recursive_remove, recursive_remove || to_remove->count(&iface));
192         TraversingVisitor::visit(iface);
193 }
194
195 void NodeRemover::visit(FunctionDeclaration &func)
196 {
197         if(to_remove->count(&func))
198                 remove_from_map(stage->functions, func.name, func);
199         TraversingVisitor::visit(func);
200 }
201
202 void NodeRemover::visit(Iteration &iter)
203 {
204         if(to_remove->count(iter.init_statement.get()))
205                 iter.init_statement = 0;
206         TraversingVisitor::visit(iter);
207 }
208
209
210 NodeReorderer::NodeReorderer():
211         reorder_before(0),
212         to_reorder(0)
213 { }
214
215 void NodeReorderer::apply(Stage &stage, Node &before, const set<Node *> &tr)
216 {
217         reorder_before = &before;
218         to_reorder = &tr;
219         stage.content.visit(*this);
220 }
221
222 void NodeReorderer::visit(Block &block)
223 {
224         NodeList<Statement>::iterator insert_point = block.body.end();
225         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
226         {
227                 (*i)->visit(*this);
228                 if(insert_point!=block.body.end() && to_reorder->count(i->get()))
229                 {
230                         NodeList<Statement>::iterator j = i++;
231                         block.body.splice(insert_point, block.body, j);
232                 }
233                 else
234                 {
235                         if(i->get()==reorder_before)
236                                 insert_point = i;
237                         ++i;
238                 }
239         }
240 }
241
242 } // namespace SL
243 } // namespace GL
244 } // namespace Msp