1 #include <msp/core/algorithm.h>
2 #include <msp/core/maputils.h>
12 const Operator Operator::operators[] =
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 }
60 const Operator &Operator::get_operator(const string &token, Type type)
62 for(const Operator *i=operators; i->type; ++i)
63 if(i->type==type && i->token==token)
65 throw key_error(token);
70 NodeContainer<C>::NodeContainer(const NodeContainer &c):
78 Block::Block(const Block &other):
81 use_braces(other.use_braces)
84 void Block::visit(NodeVisitor &visitor)
90 void Literal::visit(NodeVisitor &visitor)
96 VariableReference::VariableReference(const VariableReference &other):
101 void VariableReference::visit(NodeVisitor &visitor)
103 visitor.visit(*this);
107 InterfaceBlockReference::InterfaceBlockReference(const InterfaceBlockReference &other):
112 void InterfaceBlockReference::visit(NodeVisitor &visitor)
114 visitor.visit(*this);
118 MemberAccess::MemberAccess(const MemberAccess &other):
122 // Do not copy declaration
125 void MemberAccess::visit(NodeVisitor &visitor)
127 visitor.visit(*this);
131 void Swizzle::visit(NodeVisitor &visitor)
133 visitor.visit(*this);
137 void UnaryExpression::visit(NodeVisitor &visitor)
139 visitor.visit(*this);
143 void BinaryExpression::visit(NodeVisitor &visitor)
145 visitor.visit(*this);
149 Assignment::Assignment(const Assignment &other):
150 BinaryExpression(other),
151 self_referencing(other.self_referencing)
152 // Do not copy target
155 void Assignment::visit(NodeVisitor &visitor)
157 visitor.visit(*this);
161 bool Assignment::Target::operator<(const Target &other) const
163 if(declaration!=other.declaration)
164 return declaration<other.declaration;
165 for(unsigned i=0; (i<7 && i<chain_len && i<other.chain_len); ++i)
166 if(chain[i]!=other.chain[i])
167 return chain[i]<other.chain[i];
168 return chain_len<other.chain_len;
172 void TernaryExpression::visit(NodeVisitor &visitor)
174 visitor.visit(*this);
178 FunctionCall::FunctionCall(const FunctionCall &other):
181 constructor(other.constructor),
182 arguments(other.arguments)
183 // Do not copy declaration
186 void FunctionCall::visit(NodeVisitor &visitor)
188 visitor.visit(*this);
192 void ExpressionStatement::visit(NodeVisitor &visitor)
194 visitor.visit(*this);
198 void Import::visit(NodeVisitor &visitor)
200 visitor.visit(*this);
204 void Precision::visit(NodeVisitor &visitor)
206 visitor.visit(*this);
210 void Layout::visit(NodeVisitor &visitor)
212 visitor.visit(*this);
216 void InterfaceLayout::visit(NodeVisitor &visitor)
218 visitor.visit(*this);
222 BasicTypeDeclaration::BasicTypeDeclaration(const BasicTypeDeclaration &other):
223 TypeDeclaration(other),
227 extended_alignment(other.extended_alignment),
229 // Do not copy base type
232 void BasicTypeDeclaration::visit(NodeVisitor &visitor)
234 visitor.visit(*this);
238 void ImageTypeDeclaration::visit(NodeVisitor &visitor)
240 visitor.visit(*this);
244 StructDeclaration::StructDeclaration()
246 members.use_braces = true;
249 StructDeclaration::StructDeclaration(const StructDeclaration &other):
250 TypeDeclaration(other),
251 members(other.members),
252 extended_alignment(other.extended_alignment)
253 // Do not copy interface block
256 StructDeclaration::~StructDeclaration()
258 if(interface_block && interface_block->struct_declaration==this)
259 interface_block->struct_declaration = 0;
262 void StructDeclaration::visit(NodeVisitor &visitor)
264 visitor.visit(*this);
268 VariableDeclaration::VariableDeclaration(const VariableDeclaration &other):
270 layout(other.layout),
271 constant(other.constant),
272 sampling(other.sampling),
273 interpolation(other.interpolation),
274 interface(other.interface),
275 precision(other.precision),
279 array_size(other.array_size),
280 init_expression(other.init_expression)
281 // Do not copy type and linked declarations
284 VariableDeclaration::~VariableDeclaration()
286 if(linked_declaration && linked_declaration->linked_declaration==this)
287 linked_declaration->linked_declaration = 0;
290 void VariableDeclaration::visit(NodeVisitor &visitor)
292 visitor.visit(*this);
296 InterfaceBlock::InterfaceBlock(const InterfaceBlock &other):
298 layout(other.layout),
299 interface(other.interface),
300 block_name(other.block_name),
301 members(other.members),
302 instance_name(other.instance_name),
304 // Do not copy pointers to other nodes
307 InterfaceBlock::~InterfaceBlock()
309 if(linked_block && linked_block->linked_block==this)
310 linked_block->linked_block = 0;
311 if(struct_declaration && struct_declaration->interface_block==this)
312 struct_declaration->interface_block = 0;
315 void InterfaceBlock::visit(NodeVisitor &visitor)
317 visitor.visit(*this);
321 FunctionDeclaration::FunctionDeclaration(const FunctionDeclaration &other):
323 return_type(other.return_type),
325 parameters(other.parameters),
326 virtua(other.virtua),
327 overrd(other.overrd),
329 signature(other.signature),
330 definition(other.definition==&other ? this : 0)
331 // Do not copy return type declaration
334 void FunctionDeclaration::visit(NodeVisitor &visitor)
336 visitor.visit(*this);
340 void Conditional::visit(NodeVisitor &visitor)
342 visitor.visit(*this);
346 void Iteration::visit(NodeVisitor &visitor)
348 visitor.visit(*this);
352 void Passthrough::visit(NodeVisitor &visitor)
354 visitor.visit(*this);
358 void Return::visit(NodeVisitor &visitor)
360 visitor.visit(*this);
364 void Jump::visit(NodeVisitor &visitor)
366 visitor.visit(*this);
370 Stage::Stage(Stage::Type t):
374 const char *Stage::get_stage_name(Type type)
376 static const char *const names[] = { "shared", "vertex", "geometry", "fragment" };
382 shared(Stage::SHARED)
386 string get_unused_variable_name(const Block &block, const string &base)
391 unsigned base_size = name.size();
395 for(const Block *b=█ (unused && b); b=b->parent)
396 unused = !b->variables.count(name);
400 name.erase(base_size);
401 name += format("_%d", number);
406 const TypeDeclaration *get_ultimate_base_type(const TypeDeclaration *type)
410 while(const BasicTypeDeclaration *basic = dynamic_cast<const BasicTypeDeclaration *>(type))
412 if(!basic->base_type)
414 type = basic->base_type;
419 bool has_layout_qualifier(const Layout *layout, const string &name)
423 auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name);
424 return i!=layout->qualifiers.end();
427 int get_layout_value(const Layout *layout, const string &name, int def_value)
431 auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name);
432 return (i!=layout->qualifiers.end() ? i->value : def_value);
435 void add_layout_qualifier(RefPtr<Layout> &layout, const Layout::Qualifier &q)
439 layout->qualifiers.push_back(q);
442 void add_to_chain(Assignment::Target &target, Assignment::Target::ChainType type, unsigned index)
444 if(target.chain_len<7)
445 target.chain[target.chain_len] = type | min<unsigned>(index, 0x3F);
449 bool targets_overlap(const Assignment::Target &target1, const Assignment::Target &target2)
451 bool overlap = (target1.declaration==target2.declaration);
452 for(unsigned i=0; (overlap && i<target1.chain_len && i<target2.chain_len); ++i)
454 Assignment::Target::ChainType type1 = static_cast<Assignment::Target::ChainType>(target1.chain[i]&0xC0);
455 Assignment::Target::ChainType type2 = static_cast<Assignment::Target::ChainType>(target2.chain[i]&0xC0);
456 unsigned index1 = target1.chain[i]&0x3F;
457 unsigned index2 = target2.chain[i]&0x3F;
458 if(type1==Assignment::Target::SWIZZLE || type2==Assignment::Target::SWIZZLE)
460 if(type1==Assignment::Target::SWIZZLE && type2==Assignment::Target::SWIZZLE)
461 overlap = index1&index2;
462 else if(type1==Assignment::Target::ARRAY && index1<4)
463 overlap = index2&(1<<index1);
464 else if(type2==Assignment::Target::ARRAY && index2<4)
465 overlap = index1&(1<<index2);
466 // Treat other combinations as overlapping (shouldn't happen)
469 overlap = (type1==type2 && (index1==index2 || index1==0x3F || index2==0x3F));