for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
{
if(i->type==VERTEX)
- program.attach_shader_owned(new VertexShader(head+create_source(*i)));
+ program.attach_shader_owned(new VertexShader(head+apply<Formatter>(*i)));
else if(i->type==GEOMETRY)
- program.attach_shader_owned(new GeometryShader(head+create_source(*i)));
+ program.attach_shader_owned(new GeometryShader(head+apply<Formatter>(*i)));
else if(i->type==FRAGMENT)
- program.attach_shader_owned(new FragmentShader(head+create_source(*i)));
+ program.attach_shader_owned(new FragmentShader(head+apply<Formatter>(*i)));
}
program.bind_attribute(VERTEX4, "vertex");
bool ProgramCompiler::optimize(Stage &stage)
{
- UnusedVariableLocator unused_locator;
- unused_locator.apply(stage);
+ set<Node *> unused = apply<UnusedVariableLocator>(stage);
+ apply<NodeRemover>(stage, unused);
- NodeRemover remover;
- remover.to_remove = unused_locator.unused_nodes;
- remover.apply(stage);
-
- return !unused_locator.unused_nodes.empty();
+ return !unused.empty();
}
void ProgramCompiler::inject_block(Block &target, const Block &source)
}
template<typename T>
-void ProgramCompiler::apply(Stage &stage)
+typename T::ResultType ProgramCompiler::apply(Stage &stage)
{
T visitor;
visitor.apply(stage);
+ return visitor.get_result();
}
-string ProgramCompiler::create_source(Stage &stage)
+template<typename T, typename A>
+typename T::ResultType ProgramCompiler::apply(Stage &stage, const A &arg)
{
- Formatter formatter;
- formatter.apply(stage);
- return formatter.formatted;
+ T visitor(arg);
+ visitor.apply(stage);
+ return visitor.get_result();
}
ProgramCompiler::Formatter::Formatter():
indent(0),
parameter_list(false),
- else_if(false)
+ else_if(0)
{ }
void ProgramCompiler::Formatter::visit(Literal &literal)
void ProgramCompiler::Formatter::visit(Block &block)
{
- if(block.use_braces)
- {
- if(else_if)
- {
- formatted += '\n';
- else_if = false;
- }
- formatted += format("%s{\n", string(indent*2, ' '));
- }
+ if(else_if)
+ --else_if;
+
+ unsigned brace_indent = indent;
+ bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
+ if(use_braces)
+ formatted += format("%s{\n", string(brace_indent*2, ' '));
- bool change_indent = (!formatted.empty() && !else_if);
- indent += change_indent;
+ SetForScope<unsigned> set(indent, indent+!formatted.empty());
string spaces(indent*2, ' ');
for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
{
if(i!=block.body.begin())
formatted += '\n';
- if(!else_if)
- formatted += spaces;
+ formatted += spaces;
(*i)->visit(*this);
+ else_if = 0;
}
- indent -= change_indent;
- if(block.use_braces)
- formatted += format("\n%s}", string(indent*2, ' '));
+ if(use_braces)
+ formatted += format("\n%s}", string(brace_indent*2, ' '));
}
void ProgramCompiler::Formatter::visit(Layout &layout)
void ProgramCompiler::Formatter::visit(Conditional &cond)
{
if(else_if)
- {
- formatted += ' ';
- else_if = false;
- }
+ formatted.replace(formatted.rfind('\n'), string::npos, 1, ' ');
+
+ indent -= else_if;
formatted += "if(";
cond.condition->visit(*this);
cond.body.visit(*this);
if(!cond.else_body.body.empty())
{
- formatted += format("\n%selse", string(indent*2, ' '));
- SetFlag set(else_if);
+ formatted += format("\n%selse\n", string(indent*2, ' '));
+ SetForScope<unsigned> set(else_if, 2);
cond.else_body.visit(*this);
}
}
}
+ProgramCompiler::NodeRemover::NodeRemover(const set<Node *> &r):
+ to_remove(r)
+{ }
+
void ProgramCompiler::NodeRemover::visit(Block &block)
{
for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )