]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/syntax.cpp
Recognize unknown index as matching any index
[libs/gl.git] / source / glsl / syntax.cpp
1 #include <msp/core/algorithm.h>
2 #include <msp/core/maputils.h>
3 #include "syntax.h"
4 #include "visitor.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10 namespace SL {
11
12 const Operator Operator::operators[] =
13 {
14         { "[", "]", 2, BINARY, LEFT_TO_RIGHT },
15         { "(", ")", 2, POSTFIX, LEFT_TO_RIGHT },
16         { ".", { }, 2, POSTFIX, LEFT_TO_RIGHT },
17         { "++", { }, 2, POSTFIX, LEFT_TO_RIGHT },
18         { "--", { }, 2, POSTFIX, LEFT_TO_RIGHT },
19         { "++", { }, 3, PREFIX, RIGHT_TO_LEFT },
20         { "--", { }, 3, PREFIX, RIGHT_TO_LEFT },
21         { "+", { }, 3, PREFIX, RIGHT_TO_LEFT },
22         { "-", { }, 3, PREFIX, RIGHT_TO_LEFT },
23         { "~", { }, 3, PREFIX, RIGHT_TO_LEFT },
24         { "!", { }, 3, PREFIX, RIGHT_TO_LEFT },
25         { "*", { }, 4, BINARY, ASSOCIATIVE },
26         { "/", { }, 4, BINARY, LEFT_TO_RIGHT },
27         { "%", { }, 4, BINARY, LEFT_TO_RIGHT },
28         { "+", { }, 5, BINARY, ASSOCIATIVE },
29         { "-", { }, 5, BINARY, LEFT_TO_RIGHT },
30         { "<<", { }, 6, BINARY, LEFT_TO_RIGHT },
31         { ">>", { }, 6, BINARY, LEFT_TO_RIGHT },
32         { "<", { }, 7, BINARY, LEFT_TO_RIGHT },
33         { ">", { }, 7, BINARY, LEFT_TO_RIGHT },
34         { "<=", { }, 7, BINARY, LEFT_TO_RIGHT },
35         { ">=", { }, 7, BINARY, LEFT_TO_RIGHT },
36         { "==", { }, 8, BINARY, LEFT_TO_RIGHT },
37         { "!=", { }, 8, BINARY, LEFT_TO_RIGHT },
38         { "&", { }, 9, BINARY, ASSOCIATIVE },
39         { "^", { }, 10, BINARY, ASSOCIATIVE },
40         { "|", { }, 11, BINARY, ASSOCIATIVE },
41         { "&&", { }, 12, BINARY, ASSOCIATIVE },
42         { "^^", { }, 13, BINARY, ASSOCIATIVE },
43         { "||", { }, 14, BINARY, ASSOCIATIVE },
44         { "?", ":", 15, TERNARY, RIGHT_TO_LEFT },
45         { "=", { }, 16, BINARY, RIGHT_TO_LEFT },
46         { "+=", { }, 16, BINARY, RIGHT_TO_LEFT },
47         { "-=", { }, 16, BINARY, RIGHT_TO_LEFT },
48         { "*=", { }, 16, BINARY, RIGHT_TO_LEFT },
49         { "/=", { }, 16, BINARY, RIGHT_TO_LEFT },
50         { "%=", { }, 16, BINARY, RIGHT_TO_LEFT },
51         { "<<=", { }, 16, BINARY, RIGHT_TO_LEFT },
52         { ">>=", { }, 16, BINARY, RIGHT_TO_LEFT },
53         { "&=", { }, 16, BINARY, RIGHT_TO_LEFT },
54         { "^=", { }, 16, BINARY, RIGHT_TO_LEFT },
55         { "|=", { }, 16, BINARY, RIGHT_TO_LEFT },
56         { ",", { }, 17, BINARY, LEFT_TO_RIGHT },
57         { { 0 }, { }, 18, NO_OPERATOR, LEFT_TO_RIGHT }
58 };
59
60 const Operator &Operator::get_operator(const string &token, Type type)
61 {
62         for(const Operator *i=operators; i->type; ++i)
63                 if(i->type==type && i->token==token)
64                         return *i;
65         throw key_error(token);
66 }
67
68
69 template<typename C>
70 NodeContainer<C>::NodeContainer(const NodeContainer &c):
71         C(c)
72 {
73         for(auto &i: *this)
74                 i = i->clone();
75 }
76
77
78 Block::Block(const Block &other):
79         Node(other),
80         body(other.body),
81         use_braces(other.use_braces),
82         parent(0)
83 { }
84
85 void Block::visit(NodeVisitor &visitor)
86 {
87         visitor.visit(*this);
88 }
89
90
91 void Literal::visit(NodeVisitor &visitor)
92 {
93         visitor.visit(*this);
94 }
95
96
97 VariableReference::VariableReference(const VariableReference &other):
98         Expression(other),
99         name(other.name)
100 { }
101
102 void VariableReference::visit(NodeVisitor &visitor)
103 {
104         visitor.visit(*this);
105 }
106
107
108 InterfaceBlockReference::InterfaceBlockReference(const InterfaceBlockReference &other):
109         Expression(other),
110         name(other.name)
111 { }
112
113 void InterfaceBlockReference::visit(NodeVisitor &visitor)
114 {
115         visitor.visit(*this);
116 }
117
118
119 MemberAccess::MemberAccess(const MemberAccess &other):
120         Expression(other),
121         left(other.left),
122         member(other.member)
123         // Do not copy declaration
124 { }
125
126 void MemberAccess::visit(NodeVisitor &visitor)
127 {
128         visitor.visit(*this);
129 }
130
131
132 void Swizzle::visit(NodeVisitor &visitor)
133 {
134         visitor.visit(*this);
135 }
136
137
138 void UnaryExpression::visit(NodeVisitor &visitor)
139 {
140         visitor.visit(*this);
141 }
142
143
144 void BinaryExpression::visit(NodeVisitor &visitor)
145 {
146         visitor.visit(*this);
147 }
148
149
150 Assignment::Assignment(const Assignment &other):
151         BinaryExpression(other),
152         self_referencing(other.self_referencing)
153         // Do not copy target
154 { }
155
156 void Assignment::visit(NodeVisitor &visitor)
157 {
158         visitor.visit(*this);
159 }
160
161
162 bool Assignment::Target::operator<(const Target &other) const
163 {
164         if(declaration!=other.declaration)
165                 return declaration<other.declaration;
166         for(unsigned i=0; (i<7 && i<chain_len && i<other.chain_len); ++i)
167                 if(chain[i]!=other.chain[i])
168                         return chain[i]<other.chain[i];
169         return chain_len<other.chain_len;
170 }
171
172
173 void TernaryExpression::visit(NodeVisitor &visitor)
174 {
175         visitor.visit(*this);
176 }
177
178
179 FunctionCall::FunctionCall(const FunctionCall &other):
180         Expression(other),
181         name(other.name),
182         constructor(other.constructor),
183         arguments(other.arguments)
184         // Do not copy declaration
185 { }
186
187 void FunctionCall::visit(NodeVisitor &visitor)
188 {
189         visitor.visit(*this);
190 }
191
192
193 void ExpressionStatement::visit(NodeVisitor &visitor)
194 {
195         visitor.visit(*this);
196 }
197
198
199 void Import::visit(NodeVisitor &visitor)
200 {
201         visitor.visit(*this);
202 }
203
204
205 void Precision::visit(NodeVisitor &visitor)
206 {
207         visitor.visit(*this);
208 }
209
210
211 void Layout::visit(NodeVisitor &visitor)
212 {
213         visitor.visit(*this);
214 }
215
216
217 void InterfaceLayout::visit(NodeVisitor &visitor)
218 {
219         visitor.visit(*this);
220 }
221
222
223 BasicTypeDeclaration::BasicTypeDeclaration(const BasicTypeDeclaration &other):
224         TypeDeclaration(other),
225         kind(other.kind),
226         size(other.size),
227         sign(other.sign),
228         base(other.base)
229         // Do not copy base type
230 { }
231
232 void BasicTypeDeclaration::visit(NodeVisitor &visitor)
233 {
234         visitor.visit(*this);
235 }
236
237
238 void ImageTypeDeclaration::visit(NodeVisitor &visitor)
239 {
240         visitor.visit(*this);
241 }
242
243
244 StructDeclaration::StructDeclaration()
245 {
246         members.use_braces = true;
247 }
248
249 StructDeclaration::StructDeclaration(const StructDeclaration &other):
250         TypeDeclaration(other),
251         members(other.members)
252         // Do not copy interface block
253 { }
254
255 StructDeclaration::~StructDeclaration()
256 {
257         if(interface_block && interface_block->struct_declaration==this)
258                 interface_block->struct_declaration = 0;
259 }
260
261 void StructDeclaration::visit(NodeVisitor &visitor)
262 {
263         visitor.visit(*this);
264 }
265
266
267 VariableDeclaration::VariableDeclaration(const VariableDeclaration &other):
268         Statement(other),
269         layout(other.layout),
270         constant(other.constant),
271         sampling(other.sampling),
272         interpolation(other.interpolation),
273         interface(other.interface),
274         precision(other.precision),
275         type(other.type),
276         name(other.name),
277         array(other.array),
278         array_size(other.array_size),
279         init_expression(other.init_expression)
280         // Do not copy type and linked declarations
281 { }
282
283 VariableDeclaration::~VariableDeclaration()
284 {
285         if(linked_declaration && linked_declaration->linked_declaration==this)
286                 linked_declaration->linked_declaration = 0;
287 }
288
289 void VariableDeclaration::visit(NodeVisitor &visitor)
290 {
291         visitor.visit(*this);
292 }
293
294
295 InterfaceBlock::InterfaceBlock(const InterfaceBlock &other):
296         Statement(other),
297         interface(other.interface),
298         block_name(other.block_name),
299         members(other.members),
300         instance_name(other.instance_name),
301         array(other.array)
302         // Do not copy pointers to other nodes
303 { }
304
305 InterfaceBlock::~InterfaceBlock()
306 {
307         if(linked_block && linked_block->linked_block==this)
308                 linked_block->linked_block = 0;
309         if(struct_declaration && struct_declaration->interface_block==this)
310                 struct_declaration->interface_block = 0;
311 }
312
313 void InterfaceBlock::visit(NodeVisitor &visitor)
314 {
315         visitor.visit(*this);
316 }
317
318
319 FunctionDeclaration::FunctionDeclaration(const FunctionDeclaration &other):
320         Statement(other),
321         return_type(other.return_type),
322         name(other.name),
323         parameters(other.parameters),
324         virtua(other.virtua),
325         overrd(other.overrd),
326         body(other.body),
327         signature(other.signature),
328         definition(other.definition==&other ? this : 0)
329         // Do not copy return type declaration
330 { }
331
332 void FunctionDeclaration::visit(NodeVisitor &visitor)
333 {
334         visitor.visit(*this);
335 }
336
337
338 void Conditional::visit(NodeVisitor &visitor)
339 {
340         visitor.visit(*this);
341 }
342
343
344 void Iteration::visit(NodeVisitor &visitor)
345 {
346         visitor.visit(*this);
347 }
348
349
350 void Passthrough::visit(NodeVisitor &visitor)
351 {
352         visitor.visit(*this);
353 }
354
355
356 void Return::visit(NodeVisitor &visitor)
357 {
358         visitor.visit(*this);
359 }
360
361
362 void Jump::visit(NodeVisitor &visitor)
363 {
364         visitor.visit(*this);
365 }
366
367
368 Stage::Stage(Stage::Type t):
369         type(t),
370         previous(0)
371 { }
372
373 const char *Stage::get_stage_name(Type type)
374 {
375         static const char *const names[] = { "shared", "vertex", "geometry", "fragment" };
376         return names[type];
377 }
378
379
380 Module::Module():
381         shared(Stage::SHARED)
382 { }
383
384
385 string get_unused_variable_name(const Block &block, const string &base)
386 {
387         string name = base;
388
389         unsigned number = 1;
390         unsigned base_size = name.size();
391         while(1)
392         {
393                 bool unused = true;
394                 for(const Block *b=&block; (unused && b); b=b->parent)
395                         unused = !b->variables.count(name);
396                 if(unused)
397                         return name;
398
399                 name.erase(base_size);
400                 name += format("_%d", number);
401                 ++number;
402         }
403 }
404
405 int get_layout_value(const Layout &layout, const string &name, int def_value)
406 {
407         auto i = find_member(layout.qualifiers, name, &Layout::Qualifier::name);
408         return (i!=layout.qualifiers.end() ? i->value : def_value);
409 }
410
411 void add_to_chain(Assignment::Target &target, Assignment::Target::ChainType type, unsigned index)
412 {
413         if(target.chain_len<7)
414                 target.chain[target.chain_len] = type | min<unsigned>(index, 0x3F);
415         ++target.chain_len;
416 }
417
418 } // namespace SL
419 } // namespace GL
420 } // namespace Msp