Module *module = new Module(parser.parse(builtins_src, "<builtin>"));
for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
{
- VariableResolver resolver;
- i->content.visit(resolver);
+ VariableResolver().visit(i->content);
for(map<string, VariableDeclaration *>::iterator j=i->content.variables.begin(); j!=i->content.variables.end(); ++j)
j->second->linked_declaration = j->second;
}
namespace SL {
DefaultPrecisionGenerator::DefaultPrecisionGenerator():
+ stage_type(Stage::SHARED),
toplevel(true)
{ }
+void DefaultPrecisionGenerator::apply(Stage &stage)
+{
+ SetForScope<Stage::Type> set_stage(stage_type, stage.type);
+ visit(stage.content);
+}
+
void DefaultPrecisionGenerator::visit(Block &block)
{
if(toplevel)
BlockModifier::visit(block);
}
else
- StageVisitor::visit(block);
+ TraversingVisitor::visit(block);
}
void DefaultPrecisionGenerator::visit(Precision &prec)
Precision *prec = new Precision;
if(!type.compare(0, 7, "sampler"))
prec->precision = "lowp";
- else if(stage->type==Stage::FRAGMENT)
+ else if(stage_type==Stage::FRAGMENT)
prec->precision = "mediump";
else
prec->precision = "highp";
return true;
}
+void LegacyConverter::apply(Stage &s)
+{
+ SetForScope<Stage *> set_stage(stage, &s);
+ visit(s.content);
+}
+
bool LegacyConverter::supports_unified_interface_syntax() const
{
if(target_api==OPENGL_ES2)
class DefaultPrecisionGenerator: public BlockModifier
{
private:
+ Stage::Type stage_type;
bool toplevel;
std::set<std::string> have_default;
public:
DefaultPrecisionGenerator();
- using StageVisitor::visit;
+ void apply(Stage &);
+
+ using BlockModifier::visit;
virtual void visit(Block &);
virtual void visit(Precision &);
virtual void visit(VariableDeclaration &);
class PrecisionRemover: public BlockModifier
{
public:
- using StageVisitor::visit;
+ void apply(Stage &s) { visit(s.content); }
+
+ using BlockModifier::visit;
virtual void visit(Precision &);
virtual void visit(VariableDeclaration &);
};
class LegacyConverter: public BlockModifier
{
private:
+ Stage *stage;
GLApi target_api;
Version target_version;
std::string type;
private:
bool check_version(const Version &) const;
bool check_extension(const Extension &) const;
- using StageVisitor::visit;
+public:
+ using BlockModifier::visit;
+ virtual void apply(Stage &);
+private:
bool supports_unified_interface_syntax() const;
virtual void visit(VariableReference &);
virtual void visit(Assignment &);
{
for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
{
+ string stage_src = Formatter().apply(*i);
+
if(i->type==Stage::VERTEX)
{
- program.attach_shader_owned(new VertexShader(apply<Formatter>(*i)));
+ program.attach_shader_owned(new VertexShader(stage_src));
for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
program.bind_attribute(j->second, j->first);
}
else if(i->type==Stage::GEOMETRY)
- program.attach_shader_owned(new GeometryShader(apply<Formatter>(*i)));
+ program.attach_shader_owned(new GeometryShader(stage_src));
else if(i->type==Stage::FRAGMENT)
{
- program.attach_shader_owned(new FragmentShader(apply<Formatter>(*i)));
+ program.attach_shader_owned(new FragmentShader(stage_src));
if(EXT_gpu_shader4)
{
for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
void Compiler::append_module(Module &mod)
{
- vector<Import *> imports = apply<NodeGatherer<Import> >(mod.shared);
+ vector<Import *> imports = NodeGatherer<Import>().apply(mod.shared);
for(vector<Import *>::iterator i=imports.begin(); i!=imports.end(); ++i)
import((*i)->module);
- apply<NodeRemover>(mod.shared, set<Node *>(imports.begin(), imports.end()));
+ NodeRemover(set<Node *>(imports.begin(), imports.end())).apply(mod.shared);
append_stage(mod.shared);
for(list<Stage>::iterator i=mod.stages.begin(); i!=mod.stages.end(); ++i)
target->required_version = stage.required_version;
for(NodeList<Statement>::iterator i=stage.content.body.begin(); i!=stage.content.body.end(); ++i)
target->content.body.push_back(*i);
- apply<DeclarationCombiner>(*target);
+ DeclarationCombiner().apply(*target);
}
void Compiler::process()
stage.required_version = module->shared.required_version;
inject_block(stage.content, module->shared.content);
- apply<DeclarationReorderer>(stage);
- apply<FunctionResolver>(stage);
- apply<VariableResolver>(stage);
- apply<InterfaceGenerator>(stage);
- apply<VariableResolver>(stage);
- apply<DeclarationReorderer>(stage);
- apply<FunctionResolver>(stage);
- apply<LegacyConverter>(stage);
+ DeclarationReorderer().apply(stage);
+ FunctionResolver().apply(stage);
+ VariableResolver().apply(stage);
+ InterfaceGenerator().apply(stage);
+ VariableResolver().apply(stage);
+ DeclarationReorderer().apply(stage);
+ FunctionResolver().apply(stage);
+ LegacyConverter().apply(stage);
}
bool Compiler::optimize(Stage &stage)
{
- apply<ConstantConditionEliminator>(stage);
+ ConstantConditionEliminator().apply(stage);
- set<FunctionDeclaration *> inlineable = apply<InlineableFunctionLocator>(stage);
- apply<FunctionInliner>(stage, inlineable);
+ set<FunctionDeclaration *> inlineable = InlineableFunctionLocator().apply(stage);
+ FunctionInliner(inlineable).apply(stage);
- set<Node *> unused = apply<UnusedVariableLocator>(stage);
- set<Node *> unused2 = apply<UnusedFunctionLocator>(stage);
+ set<Node *> unused = UnusedVariableLocator().apply(stage);
+ set<Node *> unused2 = UnusedFunctionLocator().apply(stage);
unused.insert(unused2.begin(), unused2.end());
- apply<NodeRemover>(stage, unused);
+ NodeRemover(unused).apply(stage);
return !unused.empty();
}
void Compiler::finalize(Stage &stage)
{
if(get_gl_api()==OPENGL_ES2)
- apply<DefaultPrecisionGenerator>(stage);
+ DefaultPrecisionGenerator().apply(stage);
else
- apply<PrecisionRemover>(stage);
+ PrecisionRemover().apply(stage);
}
void Compiler::inject_block(Block &target, const Block &source)
target.body.insert(insert_point, (*i)->clone());
}
-template<typename T>
-typename T::ResultType Compiler::apply(Stage &stage)
-{
- T visitor;
- visitor.apply(stage);
- return visitor.get_result();
-}
-
-template<typename T, typename A>
-typename T::ResultType Compiler::apply(Stage &stage, const A &arg)
-{
- T visitor(arg);
- visitor.apply(stage);
- return visitor.get_result();
-}
-
} // namespace SL
} // namespace GL
} // namespace Msp
bool optimize(Stage &);
void finalize(Stage &);
static void inject_block(Block &, const Block &);
- template<typename T>
- static typename T::ResultType apply(Stage &);
- template<typename T, typename A>
- static typename T::ResultType apply(Stage &, const A &);
};
} // namespace SL
self_referencing(false)
{ }
-void VariableResolver::apply(Stage &s)
+void VariableResolver::apply(Stage &stage)
{
- SetForScope<Stage *> set(stage, &s);
- Stage *builtins = get_builtins(stage->type);
+ Stage *builtins = get_builtins(stage.type);
if(builtins)
blocks.push_back(&builtins->content);
- stage->content.visit(*this);
+ visit(stage.content);
if(builtins)
blocks.pop_back();
}
InterfaceGenerator::InterfaceGenerator():
+ stage(0),
scope_level(0)
{ }
if(stage->previous)
in_prefix = get_out_prefix(stage->previous->type);
out_prefix = get_out_prefix(stage->type);
- stage->content.visit(*this);
+ visit(s.content);
}
void InterfaceGenerator::visit(Block &block)
{
SetForScope<unsigned> set(scope_level, scope_level+1);
if(scope_level>1)
- return StageVisitor::visit(block);
+ return TraversingVisitor::visit(block);
NodeList<Statement>::iterator struct_insert_point = block.body.end();
NodeList<Statement>::iterator variable_insert_point = block.body.end();
void DeclarationReorderer::visit(VariableDeclaration &var)
{
- StageVisitor::visit(var);
+ TraversingVisitor::visit(var);
kind = VARIABLE;
}
public:
DeclarationCombiner();
- using StageVisitor::visit;
+ void apply(Stage &s) { visit(s.content); }
+
+ using BlockModifier::visit;
virtual void visit(Block &);
virtual void visit(FunctionDeclaration &);
virtual void visit(VariableDeclaration &);
};
-class VariableResolver: public StageVisitor
+class VariableResolver: public TraversingVisitor
{
private:
std::vector<Block *> blocks;
public:
VariableResolver();
- virtual void apply(Stage &);
- using StageVisitor::visit;
+ void apply(Stage &);
+
+ using TraversingVisitor::visit;
virtual void visit(Block &);
virtual void visit(VariableReference &);
virtual void visit(MemberAccess &);
virtual void visit(InterfaceBlock &);
};
-class FunctionResolver: public StageVisitor
+class FunctionResolver: public TraversingVisitor
{
private:
std::map<std::string, std::vector<FunctionDeclaration *> > functions;
public:
- using StageVisitor::visit;
+ void apply(Stage &s) { visit(s.content); }
+
+ using TraversingVisitor::visit;
virtual void visit(FunctionCall &);
virtual void visit(FunctionDeclaration &);
};
class InterfaceGenerator: public BlockModifier
{
private:
+ Stage *stage;
std::string in_prefix;
std::string out_prefix;
unsigned scope_level;
public:
InterfaceGenerator();
+ void apply(Stage &);
+
static std::string get_out_prefix(Stage::Type);
- virtual void apply(Stage &);
- using StageVisitor::visit;
+ using BlockModifier::visit;
virtual void visit(Block &);
std::string change_prefix(const std::string &, const std::string &) const;
bool generate_interface(VariableDeclaration &, const std::string &, const std::string &);
virtual void visit(Passthrough &);
};
-class DeclarationReorderer: public StageVisitor
+class DeclarationReorderer: public TraversingVisitor
{
private:
enum DeclarationKind
public:
DeclarationReorderer();
- using StageVisitor::visit;
+ void apply(Stage &s) { visit(s.content); }
+
+ using TraversingVisitor::visit;
virtual void visit(Block &);
virtual void visit(FunctionCall &);
virtual void visit(InterfaceLayout &) { kind = LAYOUT; }
global_scope(true)
{ }
-void UnusedVariableLocator::apply(Stage &s)
+const set<Node *> &UnusedVariableLocator::apply(Stage &s)
{
variables.push_back(BlockVariableMap());
- StageVisitor::apply(s);
+ visit(s.content);
BlockVariableMap &global_variables = variables.back();
for(BlockVariableMap::iterator i=global_variables.begin(); i!=global_variables.end(); ++i)
{
}
}
variables.pop_back();
+
+ return unused_nodes;
}
void UnusedVariableLocator::visit(VariableReference &var)
namespace GL {
namespace SL {
-class InlineableFunctionLocator: public StageVisitor
+class InlineableFunctionLocator: public TraversingVisitor
{
-public:
- typedef std::set<FunctionDeclaration *> ResultType;
-
private:
std::map<FunctionDeclaration *, unsigned> refcounts;
std::set<FunctionDeclaration *> inlineable;
public:
InlineableFunctionLocator();
- const ResultType &get_result() const { return inlineable; }
- using StageVisitor::visit;
+ const std::set<FunctionDeclaration *> &apply(Stage &s) { visit(s.content); return inlineable; }
+
+ using TraversingVisitor::visit;
virtual void visit(FunctionCall &);
virtual void visit(FunctionDeclaration &);
};
-class FunctionInliner: public StageVisitor
+class FunctionInliner: public TraversingVisitor
{
private:
std::set<FunctionDeclaration *> inlineable;
FunctionInliner();
FunctionInliner(const std::set<FunctionDeclaration *> &);
+ void apply(Stage &s) { visit(s.content); }
+
private:
void visit_and_inline(RefPtr<Expression> &);
public:
- using StageVisitor::visit;
+ using TraversingVisitor::visit;
virtual void visit(Block &);
virtual void visit(UnaryExpression &);
virtual void visit(BinaryExpression &);
public:
ConstantConditionEliminator();
- using StageVisitor::visit;
+ void apply(Stage &s) { visit(s.content); }
+
+ using BlockModifier::visit;
virtual void visit(Block &);
virtual void visit(UnaryExpression &);
virtual void visit(Assignment &);
virtual void visit(Iteration &);
};
-class UnusedVariableLocator: public StageVisitor
+class UnusedVariableLocator: public TraversingVisitor
{
-public:
- typedef std::set<Node *> ResultType;
-
private:
struct VariableInfo
{
public:
UnusedVariableLocator();
- virtual void apply(Stage &);
- const ResultType &get_result() const { return unused_nodes; }
-private:
- using StageVisitor::visit;
+ const std::set<Node *> &apply(Stage &);
+
+ using TraversingVisitor::visit;
virtual void visit(VariableReference &);
virtual void visit(MemberAccess &);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &);
+private:
void record_assignment(VariableDeclaration &, Node &, bool);
void clear_assignments(VariableInfo &, bool);
+public:
virtual void visit(ExpressionStatement &);
virtual void visit(StructDeclaration &);
virtual void visit(VariableDeclaration &);
virtual void visit(InterfaceBlock &);
virtual void visit(FunctionDeclaration &);
+private:
void merge_down_variables();
+public:
virtual void visit(Conditional &);
virtual void visit(Iteration &);
};
-class UnusedFunctionLocator: public StageVisitor
+class UnusedFunctionLocator: public TraversingVisitor
{
-public:
- typedef std::set<Node *> ResultType;
-
private:
std::set<Node *> unused_nodes;
std::set<FunctionDeclaration *> used_definitions;
public:
- const ResultType &get_result() const { return unused_nodes; }
- using StageVisitor::visit;
+ const std::set<Node *> &apply(Stage &s) { visit(s.content); return unused_nodes; }
+
+ using TraversingVisitor::visit;
virtual void visit(FunctionCall &);
virtual void visit(FunctionDeclaration &);
};
namespace SL {
Formatter::Formatter():
+ stage(0),
source_index(0),
source_line(1),
indent(0),
parameter_list(false)
{ }
-void Formatter::apply(Stage &s)
+const string &Formatter::apply(Stage &s)
{
+ SetForScope<Stage *> set_stage(stage, &s);
+
GLApi api = get_gl_api();
const Version &ver = s.required_version;
if(!s.required_extensions.empty())
formatted += '\n';
- StageVisitor::apply(s);
+ visit(s.content);
+
+ return formatted;
}
void Formatter::append(const string &text)
namespace GL {
namespace SL {
-class Formatter: public StageVisitor
+class Formatter: public TraversingVisitor
{
-public:
- typedef std::string ResultType;
-
private:
+ Stage *stage;
std::string formatted;
unsigned source_index;
unsigned source_line;
public:
Formatter();
- virtual void apply(Stage &);
- const std::string &get_result() const { return formatted; }
+ const std::string &apply(Stage &);
+
private:
void append(const std::string &);
void append(char);
void set_source(unsigned, unsigned);
public:
- using StageVisitor::visit;
+ using TraversingVisitor::visit;
virtual void visit(Block &);
virtual void visit(Literal &);
virtual void visit(ParenthesizedExpression &);
}
-StageVisitor::StageVisitor():
- stage(0)
-{ }
-
-void StageVisitor::apply(Stage &s)
-{
- SetForScope<Stage *> set(stage, &s);
- stage->content.visit(*this);
-}
-
-
BlockModifier::BlockModifier():
remove_node(false)
{ }
NodeRemover::NodeRemover(const set<Node *> &r):
+ stage(0),
to_remove(r)
{ }
+void NodeRemover::apply(Stage &s)
+{
+ SetForScope<Stage *> set_stage(stage, &s);
+ visit(s.content);
+}
+
void NodeRemover::visit(Block &block)
{
for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
virtual void visit(Return &);
};
-class StageVisitor: public TraversingVisitor
-{
-public:
- typedef void ResultType;
-
-protected:
- Stage *stage;
-
- StageVisitor();
-
-public:
- virtual void apply(Stage &);
- void get_result() const { }
-};
-
-class BlockModifier: public StageVisitor
+class BlockModifier: public TraversingVisitor
{
protected:
bool remove_node;
void apply_and_increment(Block &, NodeList<Statement>::iterator &);
public:
- using StageVisitor::visit;
+ using TraversingVisitor::visit;
virtual void visit(Block &);
};
template<typename T>
-class NodeGatherer: public StageVisitor
+class NodeGatherer: public TraversingVisitor
{
-public:
- typedef std::vector<T *> ResultType;
-
private:
std::vector<T *> nodes;
public:
- const ResultType &get_result() const { return nodes; }
- using StageVisitor::visit;
+ const std::vector<T *> &apply(Stage &s) { visit(s.content); return nodes; }
+
+ using TraversingVisitor::visit;
virtual void visit(T &n) { nodes.push_back(&n); }
};
-class NodeRemover: public StageVisitor
+class NodeRemover: public TraversingVisitor
{
private:
+ Stage *stage;
std::set<Node *> to_remove;
public:
- NodeRemover() { }
NodeRemover(const std::set<Node *> &);
- using StageVisitor::visit;
+ void apply(Stage &);
+
+ using TraversingVisitor::visit;
virtual void visit(Block &);
virtual void visit(VariableDeclaration &);
virtual void visit(Iteration &);