1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
11 Formatter::Formatter():
19 const string &Formatter::apply(Stage &s)
23 const Version &ver = s.required_features.glsl_version;
27 append(format("#version %d%02d", ver.major, ver.minor));
28 if(s.required_features.gl_api==OPENGL_ES2 && ver>=Version(3, 0))
33 if(s.required_features.arb_explicit_attrib_location)
34 append("#extension arb_explicit_attrib_location: require\n");
35 if(s.required_features.arb_gpu_shader5)
36 append("#extension arb_gpu_shader5: require\n");
37 if(s.required_features.arb_uniform_buffer_object)
38 append("#extension arb_uniform_buffer_object: require\n");
39 if(s.required_features.ext_gpu_shader4)
40 append("#extension ext_gpu_shader4: require\n");
41 if(s.required_features.ext_texture_array)
42 append("#extension ext_texture_array: require\n");
45 s.content.visit(*this);
50 void Formatter::append(const string &text)
53 for(string::const_iterator i=text.begin(); i!=text.end(); ++i)
58 void Formatter::append(char c)
65 void Formatter::set_source(unsigned index, unsigned line)
67 if(index!=source_index || (index && line!=source_line))
69 if(index==source_index && line==source_line+1)
74 if(stage && stage->required_features.glsl_version && stage->required_features.glsl_version<Version(3, 30))
76 formatted += format("#line %d %d\n", l, index);
83 void Formatter::visit(Block &block)
85 unsigned brace_indent = indent;
86 bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
88 append(format("%s{\n", string(brace_indent*2, ' ')));
90 SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
91 string spaces(indent*2, ' ');
93 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
95 if((*i)->source<=BUILTIN_SOURCE)
100 set_source((*i)->source, (*i)->line);
106 append(format("\n%s}", string(brace_indent*2, ' ')));
109 void Formatter::visit(Literal &literal)
111 append(literal.token);
114 void Formatter::visit(ParenthesizedExpression &parexpr)
117 parexpr.expression->visit(*this);
121 void Formatter::visit(VariableReference &var)
126 void Formatter::visit(InterfaceBlockReference &iface)
131 void Formatter::visit(MemberAccess &memacc)
133 memacc.left->visit(*this);
134 append(format(".%s", memacc.member));
137 void Formatter::visit(Swizzle &swizzle)
139 swizzle.left->visit(*this);
140 append(format(".%s", swizzle.component_group));
143 void Formatter::visit(UnaryExpression &unary)
145 if(unary.oper->type==Operator::PREFIX)
146 append(unary.oper->token);
147 unary.expression->visit(*this);
148 if(unary.oper->type==Operator::POSTFIX)
149 append(unary.oper->token);
152 void Formatter::visit(BinaryExpression &binary)
154 binary.left->visit(*this);
155 append(binary.oper->token);
156 binary.right->visit(*this);
157 if(binary.oper->token[0]=='[')
161 void Formatter::visit(Assignment &assign)
163 assign.left->visit(*this);
164 append(format(" %s ", assign.oper->token));
165 assign.right->visit(*this);
168 void Formatter::visit(FunctionCall &call)
170 append(format("%s(", call.name));
171 for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
173 if(i!=call.arguments.begin())
180 void Formatter::visit(ExpressionStatement &expr)
182 expr.expression->visit(*this);
186 void Formatter::visit(Import &import)
188 append(format("import %s;", import.module));
191 void Formatter::visit(Precision &prec)
193 append(format("precision %s %s;", prec.precision, prec.type));
196 void Formatter::visit(Layout &layout)
199 for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)
201 if(i!=layout.qualifiers.begin())
205 append(format("=%d", i->value));
210 void Formatter::visit(InterfaceLayout &layout)
212 layout.layout.visit(*this);
213 append(format(" %s;", layout.interface));
216 void Formatter::visit(StructDeclaration &strct)
218 append(format("struct %s\n", strct.name));
219 strct.members.visit(*this);
223 void Formatter::visit(VariableDeclaration &var)
227 var.layout->visit(*this);
232 if(!var.interpolation.empty())
233 append(format("%s ", var.interpolation));
234 if(!var.sampling.empty())
235 append(format("%s ", var.sampling));
236 if(!var.interface.empty())
238 string interface = var.interface;
239 if(stage && stage->required_features.glsl_version && stage->required_features.glsl_version<Version(1, 30))
241 if(stage->type==Stage::VERTEX && var.interface=="in")
242 interface = "attribute";
243 else if((stage->type==Stage::VERTEX && var.interface=="out") || (stage->type==Stage::FRAGMENT && var.interface=="in"))
244 interface = "varying";
246 append(format("%s ", interface));
248 if(!var.precision.empty())
249 append(format("%s ", var.precision));
250 string type_name = var.type_declaration->name;
252 type_name = type_name.substr(0, type_name.find('['));
253 append(format("%s %s", type_name, var.name));
258 var.array_size->visit(*this);
261 if(var.init_expression)
264 var.init_expression->visit(*this);
270 void Formatter::visit(InterfaceBlock &iface)
272 append(format("%s %s\n", iface.interface, iface.name));
273 if(iface.struct_declaration)
274 iface.struct_declaration->members.visit(*this);
275 if(!iface.instance_name.empty())
278 append(iface.instance_name);
285 void Formatter::visit(FunctionDeclaration &func)
287 append(format("%s %s(", func.return_type_declaration->name, func.name));
288 for(NodeArray<VariableDeclaration>::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
290 if(i!=func.parameters.begin())
292 SetFlag set(parameter_list);
296 if(func.definition==&func)
299 func.body.visit(*this);
305 void Formatter::visit(Conditional &cond)
308 cond.condition->visit(*this);
311 cond.body.visit(*this);
312 if(!cond.else_body.body.empty())
314 Conditional *else_cond = dynamic_cast<Conditional *>(cond.else_body.body.front().get());
315 if(cond.else_body.body.size()==1 && else_cond)
318 set_source(else_cond->source, else_cond->line);
319 append(format("%selse ", string(indent*2, ' ')));
320 else_cond->visit(*this);
324 append(format("\n%selse\n", string(indent*2, ' ')));
325 cond.else_body.visit(*this);
330 void Formatter::visit(Iteration &iter)
332 if(!iter.init_statement && iter.condition && !iter.loop_expression)
335 iter.condition->visit(*this);
341 if(iter.init_statement)
342 iter.init_statement->visit(*this);
348 iter.condition->visit(*this);
351 if(iter.loop_expression)
354 iter.loop_expression->visit(*this);
359 if(iter.body.body.empty())
364 iter.body.visit(*this);
368 void Formatter::visit(Passthrough &pass)
370 append("passthrough");
374 pass.subscript->visit(*this);
380 void Formatter::visit(Return &ret)
386 ret.expression->visit(*this);
391 void Formatter::visit(Jump &jump)
393 append(jump.keyword);