1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
11 Formatter::Formatter():
19 const string &Formatter::apply(Stage &s)
21 SetForScope<Stage *> set_stage(stage, &s);
23 GLApi api = get_gl_api();
24 const Version &ver = s.required_version;
28 append(format("#version %d%02d", ver.major, ver.minor));
29 if(api==OPENGL_ES2 && ver>=Version(3, 0))
34 for(vector<const Extension *>::const_iterator i=s.required_extensions.begin(); i!=s.required_extensions.end(); ++i)
35 append(format("#extension %s: require\n", (*i)->get_name()));
36 if(!s.required_extensions.empty())
44 void Formatter::append(const string &text)
47 for(string::const_iterator i=text.begin(); i!=text.end(); ++i)
52 void Formatter::append(char c)
59 void Formatter::set_source(unsigned index, unsigned line)
61 if(index!=source_index || (index && line!=source_line))
63 if(index==source_index && line==source_line+1)
68 if(stage->required_version<Version(3, 30))
70 formatted += format("#line %d %d\n", l, index);
77 void Formatter::visit(Literal &literal)
79 append(literal.token);
82 void Formatter::visit(ParenthesizedExpression &parexpr)
85 parexpr.expression->visit(*this);
89 void Formatter::visit(VariableReference &var)
94 void Formatter::visit(MemberAccess &memacc)
96 memacc.left->visit(*this);
97 append(format(".%s", memacc.member));
100 void Formatter::visit(UnaryExpression &unary)
104 unary.expression->visit(*this);
109 void Formatter::visit(BinaryExpression &binary)
111 binary.left->visit(*this);
113 binary.right->visit(*this);
114 append(binary.after);
117 void Formatter::visit(Assignment &assign)
119 assign.left->visit(*this);
120 append(format(" %s ", assign.oper));
121 assign.right->visit(*this);
124 void Formatter::visit(FunctionCall &call)
126 append(format("%s(", call.name));
127 for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
129 if(i!=call.arguments.begin())
136 void Formatter::visit(ExpressionStatement &expr)
138 expr.expression->visit(*this);
142 void Formatter::visit(Block &block)
144 unsigned brace_indent = indent;
145 bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
147 append(format("%s{\n", string(brace_indent*2, ' ')));
149 SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
150 string spaces(indent*2, ' ');
151 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
153 if(i!=block.body.begin())
155 set_source((*i)->source, (*i)->line);
161 append(format("\n%s}", string(brace_indent*2, ' ')));
164 void Formatter::visit(Import &import)
166 append(format("import %s;", import.module));
169 void Formatter::visit(Precision &prec)
171 append(format("precision %s %s;", prec.precision, prec.type));
174 void Formatter::visit(Layout &layout)
177 for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)
179 if(i!=layout.qualifiers.begin())
181 append(i->identifier);
182 if(!i->value.empty())
183 append(format("=%s", i->value));
188 void Formatter::visit(InterfaceLayout &layout)
190 layout.layout.visit(*this);
191 append(format(" %s;", layout.interface));
194 void Formatter::visit(StructDeclaration &strct)
196 append(format("struct %s\n", strct.name));
197 strct.members.visit(*this);
201 void Formatter::visit(VariableDeclaration &var)
205 var.layout->visit(*this);
210 if(!var.interpolation.empty())
211 append(format("%s ", var.interpolation));
212 if(!var.sampling.empty())
213 append(format("%s ", var.sampling));
214 if(!var.interface.empty() && var.interface!=block_interface)
216 string interface = var.interface;
217 if(stage->required_version<Version(1, 30))
219 if(stage->type==Stage::VERTEX && var.interface=="in")
220 interface = "attribute";
221 else if((stage->type==Stage::VERTEX && var.interface=="out") || (stage->type==Stage::FRAGMENT && var.interface=="in"))
222 interface = "varying";
224 append(format("%s ", interface));
226 if(!var.precision.empty())
227 append(format("%s ", var.precision));
228 append(format("%s %s", var.type, var.name));
233 var.array_size->visit(*this);
236 if(var.init_expression)
239 var.init_expression->visit(*this);
245 void Formatter::visit(InterfaceBlock &iface)
247 SetForScope<string> set(block_interface, iface.interface);
248 append(format("%s %s\n", iface.interface, iface.name));
249 iface.members.visit(*this);
253 void Formatter::visit(FunctionDeclaration &func)
255 append(format("%s %s(", func.return_type, func.name));
256 for(NodeArray<VariableDeclaration>::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
258 if(i!=func.parameters.begin())
260 SetFlag set(parameter_list);
264 if(func.definition==&func)
267 func.body.visit(*this);
273 void Formatter::visit(Conditional &cond)
276 cond.condition->visit(*this);
279 cond.body.visit(*this);
280 if(!cond.else_body.body.empty())
282 Conditional *else_cond = dynamic_cast<Conditional *>(cond.else_body.body.front().get());
283 if(cond.else_body.body.size()==1 && else_cond)
286 set_source(else_cond->source, else_cond->line);
287 append(format("%selse ", string(indent*2, ' ')));
288 else_cond->visit(*this);
292 append(format("\n%selse\n", string(indent*2, ' ')));
293 cond.else_body.visit(*this);
298 void Formatter::visit(Iteration &iter)
300 if(!iter.init_statement && iter.condition && !iter.loop_expression)
303 iter.condition->visit(*this);
309 if(iter.init_statement)
310 iter.init_statement->visit(*this);
316 iter.condition->visit(*this);
319 if(iter.loop_expression)
322 iter.loop_expression->visit(*this);
327 if(iter.body.body.empty())
332 iter.body.visit(*this);
336 void Formatter::visit(Return &ret)
342 ret.expression->visit(*this);
347 void Formatter::visit(Jump &jump)
349 append(jump.keyword);