X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=1da80bab07871f02befd3a2cc960b22ab1ebd486;hb=70f9fe2964700fc199ab3cabb26f9b14d078c56b;hp=b08f1737e4d542610d1a9401f37ac3df90e580cd;hpb=6e6ee01b68056b23c6709d7f60396710dd7623b9;p=libs%2Fgl.git diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index b08f1737..1da80bab 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -19,11 +19,13 @@ ProgramCompiler::ProgramCompiler(): void ProgramCompiler::compile(const string &source) { module = &parser.parse(source); + process(); } void ProgramCompiler::compile(IO::Base &io) { module = &parser.parse(io); + process(); } void ProgramCompiler::add_shaders(Program &program) @@ -31,13 +33,13 @@ void ProgramCompiler::add_shaders(Program &program) if(!module) throw invalid_operation("ProgramCompiler::add_shaders"); - string global_source = "#version 150\n"+format_context(module->global_context); + string head = "#version 150\n"; if(module->vertex_context.present) - program.attach_shader_owned(new VertexShader(global_source+"\n"+format_context(module->vertex_context))); + program.attach_shader_owned(new VertexShader(head+format_context(module->vertex_context))); if(module->geometry_context.present) - program.attach_shader_owned(new GeometryShader(global_source+"\n"+format_context(module->geometry_context))); + program.attach_shader_owned(new GeometryShader(head+format_context(module->geometry_context))); if(module->fragment_context.present) - program.attach_shader_owned(new FragmentShader(global_source+"\n"+format_context(module->fragment_context))); + program.attach_shader_owned(new FragmentShader(head+format_context(module->fragment_context))); program.bind_attribute(VERTEX4, "vertex"); program.bind_attribute(NORMAL3, "normal"); @@ -45,6 +47,28 @@ void ProgramCompiler::add_shaders(Program &program) program.bind_attribute(TEXCOORD4, "texcoord"); } +void ProgramCompiler::process() +{ + if(module->vertex_context.present) + process(module->vertex_context); + if(module->geometry_context.present) + process(module->geometry_context); + if(module->fragment_context.present) + process(module->fragment_context); +} + +void ProgramCompiler::process(Context &context) +{ + inject_block(context.content, module->global_context.content); +} + +void ProgramCompiler::inject_block(Block &target, const Block &source) +{ + list >::iterator insert_point = target.body.begin(); + for(list >::const_iterator i=source.body.begin(); i!=source.body.end(); ++i) + target.body.insert(insert_point, (*i)->clone()); +} + string ProgramCompiler::format_context(Context &context) { Formatter formatter; @@ -59,14 +83,65 @@ ProgramCompiler::Formatter::Formatter(): else_if(false) { } -string ProgramCompiler::Formatter::format_expression(Expression &expr) +void ProgramCompiler::Formatter::visit(Literal &literal) { - return join(expr.tokens.begin(), expr.tokens.end(), string()); + formatted += literal.token; +} + +void ProgramCompiler::Formatter::visit(ParenthesizedExpression &parexpr) +{ + formatted += '('; + parexpr.expression->visit(*this); + formatted += ')'; +} + +void ProgramCompiler::Formatter::visit(VariableReference &var) +{ + formatted += var.name; +} + +void ProgramCompiler::Formatter::visit(MemberAccess &memacc) +{ + memacc.left->visit(*this); + formatted += format(".%s", memacc.member); +} + +void ProgramCompiler::Formatter::visit(UnaryExpression &unary) +{ + if(unary.prefix) + formatted += unary.oper; + unary.expression->visit(*this); + if(!unary.prefix) + formatted += unary.oper; +} + +void ProgramCompiler::Formatter::visit(BinaryExpression &binary) +{ + binary.left->visit(*this); + if(binary.assignment) + formatted += format(" %s ", binary.oper); + else + formatted += binary.oper; + binary.right->visit(*this); + formatted += binary.after; +} + +void ProgramCompiler::Formatter::visit(FunctionCall &call) +{ + formatted += format("%s(", call.name); + for(vector >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) + { + if(i!=call.arguments.begin()) + formatted += ", "; + (*i)->visit(*this); + } + formatted += ')'; } void ProgramCompiler::Formatter::visit(ExpressionStatement &expr) { - formatted += format("%s;", format_expression(expr.expression)); + expr.expression->visit(*this); + formatted += ';'; } void ProgramCompiler::Formatter::visit(Block &block) @@ -84,7 +159,7 @@ void ProgramCompiler::Formatter::visit(Block &block) bool change_indent = (!formatted.empty() && !else_if); indent += change_indent; string spaces(indent*2, ' '); - for(vector::const_iterator i=block.body.begin(); i!=block.body.end(); ++i) + for(list >::iterator i=block.body.begin(); i!=block.body.end(); ++i) { if(i!=block.body.begin()) formatted += '\n'; @@ -129,9 +204,17 @@ void ProgramCompiler::Formatter::visit(VariableDeclaration &var) formatted += format("%s ", var.interface); formatted += format("%s %s", var.type, var.name); if(var.array) - formatted += format("[%s]", format_expression(var.array_size)); - if(!var.init_expression.empty()) - formatted += format(" = %s", format_expression(var.init_expression)); + { + formatted += '['; + if(var.array_size) + var.array_size->visit(*this); + formatted += ']'; + } + if(var.init_expression) + { + formatted += " = "; + var.init_expression->visit(*this); + } if(!parameter_list) formatted += ';'; } @@ -147,7 +230,7 @@ void ProgramCompiler::Formatter::visit(FunctionDeclaration &func) { formatted += format("%s %s(", func.return_type, func.name); parameter_list = true; - for(vector::const_iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) + for(vector >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) { if(i!=func.parameters.begin()) formatted += ", "; @@ -171,7 +254,11 @@ void ProgramCompiler::Formatter::visit(Conditional &cond) formatted += ' '; else_if = false; } - formatted += format("if(%s)\n", format_expression(cond.condition)); + + formatted += "if("; + cond.condition->visit(*this); + formatted += ")\n"; + cond.body.visit(*this); if(!cond.else_body.body.empty()) { @@ -186,13 +273,19 @@ void ProgramCompiler::Formatter::visit(Iteration &iter) { formatted += "for("; iter.init_statement->visit(*this); - formatted += format(" %s; %s)\n", format_expression(iter.condition), format_expression(iter.loop_expression)); + formatted += ' '; + iter.condition->visit(*this); + formatted += "; "; + iter.loop_expression->visit(*this); + formatted += ")\n"; iter.body.visit(*this); } void ProgramCompiler::Formatter::visit(Return &ret) { - formatted += format("return %s;", format_expression(ret.expression)); + formatted += "return "; + ret.expression->visit(*this); + formatted += ';'; } } // namespace GL