1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
11 Formatter::Formatter():
13 mode(Compiler::PROGRAM),
20 const string &Formatter::apply(Stage &s, Compiler::Mode m)
25 GLApi api = get_gl_api();
26 const Version &ver = s.required_version;
30 append(format("#version %d%02d", ver.major, ver.minor));
31 if(api==OPENGL_ES2 && ver>=Version(3, 0))
36 for(vector<const Extension *>::const_iterator i=s.required_extensions.begin(); i!=s.required_extensions.end(); ++i)
37 append(format("#extension %s: require\n", (*i)->get_name()));
38 if(!s.required_extensions.empty())
46 void Formatter::append(const string &text)
49 for(string::const_iterator i=text.begin(); i!=text.end(); ++i)
54 void Formatter::append(char c)
61 void Formatter::set_source(unsigned index, unsigned line)
63 if(index!=source_index || (index && line!=source_line))
65 if(index==source_index && line==source_line+1)
70 if(mode==Compiler::PROGRAM && stage && stage->required_version<Version(3, 30))
72 formatted += format("#line %d %d\n", l, index);
79 void Formatter::visit(Literal &literal)
81 append(literal.token);
84 void Formatter::visit(ParenthesizedExpression &parexpr)
87 parexpr.expression->visit(*this);
91 void Formatter::visit(VariableReference &var)
96 void Formatter::visit(MemberAccess &memacc)
98 memacc.left->visit(*this);
99 append(format(".%s", memacc.member));
102 void Formatter::visit(UnaryExpression &unary)
106 unary.expression->visit(*this);
111 void Formatter::visit(BinaryExpression &binary)
113 binary.left->visit(*this);
115 binary.right->visit(*this);
116 append(binary.after);
119 void Formatter::visit(Assignment &assign)
121 assign.left->visit(*this);
122 append(format(" %s ", assign.oper));
123 assign.right->visit(*this);
126 void Formatter::visit(FunctionCall &call)
128 append(format("%s(", call.name));
129 for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
131 if(i!=call.arguments.begin())
138 void Formatter::visit(ExpressionStatement &expr)
140 expr.expression->visit(*this);
144 void Formatter::visit(Block &block)
146 unsigned brace_indent = indent;
147 bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
149 append(format("%s{\n", string(brace_indent*2, ' ')));
151 SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
152 string spaces(indent*2, ' ');
153 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
155 if(i!=block.body.begin())
157 set_source((*i)->source, (*i)->line);
163 append(format("\n%s}", string(brace_indent*2, ' ')));
166 void Formatter::visit(Import &import)
168 append(format("import %s;", import.module));
171 void Formatter::visit(Precision &prec)
173 append(format("precision %s %s;", prec.precision, prec.type));
176 void Formatter::visit(Layout &layout)
179 for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)
181 if(i!=layout.qualifiers.begin())
183 append(i->identifier);
184 if(!i->value.empty())
185 append(format("=%s", i->value));
190 void Formatter::visit(InterfaceLayout &layout)
192 layout.layout.visit(*this);
193 append(format(" %s;", layout.interface));
196 void Formatter::visit(StructDeclaration &strct)
198 append(format("struct %s\n", strct.name));
199 strct.members.visit(*this);
203 void Formatter::visit(VariableDeclaration &var)
207 var.layout->visit(*this);
212 if(!var.interpolation.empty())
213 append(format("%s ", var.interpolation));
214 if(!var.sampling.empty())
215 append(format("%s ", var.sampling));
216 if(!var.interface.empty() && var.interface!=block_interface)
218 string interface = var.interface;
219 if(mode==Compiler::PROGRAM && stage && stage->required_version<Version(1, 30))
221 if(stage->type==Stage::VERTEX && var.interface=="in")
222 interface = "attribute";
223 else if((stage->type==Stage::VERTEX && var.interface=="out") || (stage->type==Stage::FRAGMENT && var.interface=="in"))
224 interface = "varying";
226 append(format("%s ", interface));
228 if(!var.precision.empty())
229 append(format("%s ", var.precision));
230 append(format("%s %s", var.type, var.name));
235 var.array_size->visit(*this);
238 if(var.init_expression)
241 var.init_expression->visit(*this);
247 void Formatter::visit(InterfaceBlock &iface)
249 SetForScope<string> set(block_interface, iface.interface);
250 append(format("%s %s\n", iface.interface, iface.name));
251 iface.members.visit(*this);
255 void Formatter::visit(FunctionDeclaration &func)
257 append(format("%s %s(", func.return_type, func.name));
258 for(NodeArray<VariableDeclaration>::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
260 if(i!=func.parameters.begin())
262 SetFlag set(parameter_list);
266 if(func.definition==&func)
269 func.body.visit(*this);
275 void Formatter::visit(Conditional &cond)
278 cond.condition->visit(*this);
281 cond.body.visit(*this);
282 if(!cond.else_body.body.empty())
284 Conditional *else_cond = dynamic_cast<Conditional *>(cond.else_body.body.front().get());
285 if(cond.else_body.body.size()==1 && else_cond)
288 set_source(else_cond->source, else_cond->line);
289 append(format("%selse ", string(indent*2, ' ')));
290 else_cond->visit(*this);
294 append(format("\n%selse\n", string(indent*2, ' ')));
295 cond.else_body.visit(*this);
300 void Formatter::visit(Iteration &iter)
302 if(!iter.init_statement && iter.condition && !iter.loop_expression)
305 iter.condition->visit(*this);
311 if(iter.init_statement)
312 iter.init_statement->visit(*this);
318 iter.condition->visit(*this);
321 if(iter.loop_expression)
324 iter.loop_expression->visit(*this);
329 if(iter.body.body.empty())
334 iter.body.visit(*this);
338 void Formatter::visit(Return &ret)
344 ret.expression->visit(*this);
349 void Formatter::visit(Jump &jump)
351 append(jump.keyword);