X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=82a324dec52d8e7c9e92b8d8c56cb15264e423f3;hp=63939409fc4c7d28c6f38cc031925cacb919257f;hb=a0caabaed3aeb8947133d78986bfb4ae5ae3c893;hpb=7434b80c452eb8f7ac8200a6f693a9eb668421f0 diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 63939409..82a324de 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -4,6 +4,7 @@ #include "error.h" #include "program.h" #include "programcompiler.h" +#include "resources.h" #include "shader.h" using namespace std; @@ -34,17 +35,20 @@ namespace GL { using namespace ProgramSyntax; ProgramCompiler::ProgramCompiler(): + resources(0), module(0) { } void ProgramCompiler::compile(const string &source) { + resources = 0; module = &parser.parse(source); process(); } -void ProgramCompiler::compile(IO::Base &io) +void ProgramCompiler::compile(IO::Base &io, Resources *res) { + resources = res; module = &parser.parse(io); process(); } @@ -102,6 +106,11 @@ Stage *ProgramCompiler::get_builtins(StageType type) void ProgramCompiler::process() { + list imports = apply >(module->shared); + for(list::iterator i=imports.end(); i!=imports.begin(); ) + import((*--i)->module); + apply(module->shared, set(imports.begin(), imports.end())); + for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) generate(*i); for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ) @@ -113,6 +122,39 @@ void ProgramCompiler::process() } } +void ProgramCompiler::import(const string &name) +{ + if(!resources) + throw runtime_error("no resources"); + RefPtr io = resources->open_raw(name+".glsl"); + if(!io) + throw runtime_error(format("module %s not found", name)); + ProgramParser import_parser; + Module &imported_module = import_parser.parse(*io); + + inject_block(module->shared.content, imported_module.shared.content); + apply(module->shared); + for(list::iterator i=imported_module.stages.begin(); i!=imported_module.stages.end(); ++i) + { + list::iterator j; + for(j=module->stages.begin(); (j!=module->stages.end() && j->typetype); ++j) ; + if(j==module->stages.end() || j->type>i->type) + { + j = module->stages.insert(j, *i); + list::iterator k = j; + if(++k!=module->stages.end()) + k->previous = &*j; + if(j!=module->stages.begin()) + j->previous = &*--(k=j); + } + else + { + inject_block(j->content, i->content); + apply(*j); + } + } +} + void ProgramCompiler::generate(Stage &stage) { inject_block(stage.content, module->shared.content); @@ -262,6 +304,11 @@ void ProgramCompiler::Formatter::visit(Block &block) formatted += format("\n%s}", string(brace_indent*2, ' ')); } +void ProgramCompiler::Formatter::visit(Import &import) +{ + formatted += format("import %s;", import.module); +} + void ProgramCompiler::Formatter::visit(Layout &layout) { formatted += "layout("; @@ -327,7 +374,7 @@ void ProgramCompiler::Formatter::visit(FunctionDeclaration &func) (*i)->visit(*this); } formatted += ')'; - if(func.definition) + if(func.definition==&func) { formatted += '\n'; func.body.visit(*this); @@ -376,6 +423,56 @@ void ProgramCompiler::Formatter::visit(Return &ret) } +ProgramCompiler::DeclarationCombiner::DeclarationCombiner(): + toplevel(true), + remove_node(false) +{ } + +void ProgramCompiler::DeclarationCombiner::visit(Block &block) +{ + if(!toplevel) + return; + + SetForScope set(toplevel, false); + for(list >::iterator i=block.body.begin(); i!=block.body.end(); ) + { + remove_node = false; + (*i)->visit(*this); + if(remove_node) + block.body.erase(i++); + else + ++i; + } +} + +void ProgramCompiler::DeclarationCombiner::visit(FunctionDeclaration &func) +{ + vector &decls = functions[func.name]; + if(func.definition) + { + for(vector::iterator i=decls.begin(); i!=decls.end(); ++i) + { + (*i)->definition = func.definition; + (*i)->body.body.clear(); + } + } + decls.push_back(&func); +} + +void ProgramCompiler::DeclarationCombiner::visit(VariableDeclaration &var) +{ + VariableDeclaration *&ptr = variables[var.name]; + if(ptr) + { + if(var.init_expression) + ptr->init_expression = var.init_expression; + remove_node = true; + } + else + ptr = &var; +} + + ProgramCompiler::VariableResolver::VariableResolver(): anonymous(false), record_target(false),