X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Foutput.cpp;h=f1e9b4be99ca8a2582e7a97944c0c16666f80540;hb=bde40be11da83206f3d33a8225963d47a413662e;hp=b277ba8ee09fef2b2c38c4152dc136982c16d68f;hpb=f526938b407e061c7424adedc34af4d1ff687f90;p=libs%2Fgl.git diff --git a/source/glsl/output.cpp b/source/glsl/output.cpp index b277ba8e..f1e9b4be 100644 --- a/source/glsl/output.cpp +++ b/source/glsl/output.cpp @@ -10,17 +10,17 @@ namespace SL { Formatter::Formatter(): stage(0), - mode(Compiler::PROGRAM), source_index(0), source_line(1), indent(0), - parameter_list(false) + parameter_list(false), + omit_builtin(false) { } -const string &Formatter::apply(Stage &s, Compiler::Mode m) +const string &Formatter::apply(Stage &s) { - mode = m; stage = &s; + omit_builtin = true; const Version &ver = s.required_features.glsl_version; @@ -73,7 +73,7 @@ void Formatter::set_source(unsigned index, unsigned line) else { unsigned l = line; - if(mode==Compiler::PROGRAM && stage && stage->required_features.glsl_versionrequired_features.glsl_version && stage->required_features.glsl_version::iterator i=block.body.begin(); i!=block.body.end(); ++i) { - if((*i)->source<=BUILTIN_SOURCE) + if(omit_builtin && (*i)->source<=BUILTIN_SOURCE) continue; if(!first) append('\n'); @@ -108,6 +108,38 @@ void Formatter::visit(Block &block) append(format("\n%s}", string(brace_indent*2, ' '))); } +void Formatter::visit_expression(Expression &expr, const Operator *outer_oper, bool on_rhs) +{ + unsigned outer_precedence = (outer_oper ? outer_oper->precedence : 20); + unsigned inner_precedence = (expr.oper ? expr.oper->precedence : 0); + + bool needs_parentheses = (inner_precedence>=outer_precedence); + + // Omit parentheses if the outer operator encloses this operand. + if(outer_oper && outer_oper->type==Operator::BINARY && outer_oper->token2[0] && on_rhs) + needs_parentheses = false; + + if(expr.oper) + { + /* Omit parentheses if the inner expression's operator sits between the + expression and the outer operator. */ + bool oper_on_left = expr.oper->type==Operator::PREFIX; + bool oper_on_right = expr.oper->type==Operator::POSTFIX || (expr.oper->type==Operator::BINARY && expr.oper->token2[0]); + if(expr.oper && ((oper_on_left && on_rhs) || (oper_on_right && !on_rhs))) + needs_parentheses = false; + + // Omit parentheses if the operator's natural grouping works out. + if(expr.oper==outer_oper) + needs_parentheses = (expr.oper->assoc!=Operator::ASSOCIATIVE && on_rhs!=(expr.oper->assoc==Operator::RIGHT_TO_LEFT)); + } + + if(needs_parentheses) + append('('); + expr.visit(*this); + if(needs_parentheses) + append(')'); +} + void Formatter::visit(Literal &literal) { append(literal.token); @@ -132,13 +164,13 @@ void Formatter::visit(InterfaceBlockReference &iface) void Formatter::visit(MemberAccess &memacc) { - memacc.left->visit(*this); + visit_expression(*memacc.left, memacc.oper, false); append(format(".%s", memacc.member)); } void Formatter::visit(Swizzle &swizzle) { - swizzle.left->visit(*this); + visit_expression(*swizzle.left, swizzle.oper, false); append(format(".%s", swizzle.component_group)); } @@ -146,25 +178,35 @@ void Formatter::visit(UnaryExpression &unary) { if(unary.oper->type==Operator::PREFIX) append(unary.oper->token); - unary.expression->visit(*this); + visit_expression(*unary.expression, unary.oper, unary.oper->type==Operator::PREFIX); if(unary.oper->type==Operator::POSTFIX) append(unary.oper->token); } void Formatter::visit(BinaryExpression &binary) { - binary.left->visit(*this); + visit_expression(*binary.left, binary.oper, false); append(binary.oper->token); - binary.right->visit(*this); - if(binary.oper->token[0]=='[') - append(']'); + visit_expression(*binary.right, binary.oper, true); + if(binary.oper->token2[0]) + append(binary.oper->token2); } void Formatter::visit(Assignment &assign) { - assign.left->visit(*this); + visit_expression(*assign.left, assign.oper, false); append(format(" %s ", assign.oper->token)); - assign.right->visit(*this); + visit_expression(*assign.right, assign.oper, true); +} + +void Formatter::visit(TernaryExpression &ternary) +{ + visit_expression(*ternary.condition, ternary.oper, false); + append(ternary.oper->token); + visit_expression(*ternary.true_expr, ternary.oper, false); + if(ternary.oper->token2) + append(ternary.oper->token2); + visit_expression(*ternary.false_expr, ternary.oper, true); } void Formatter::visit(FunctionCall &call) @@ -238,7 +280,7 @@ void Formatter::visit(VariableDeclaration &var) if(!var.interface.empty()) { string interface = var.interface; - if(mode==Compiler::PROGRAM && stage && stage->required_features.glsl_versionrequired_features.glsl_version && stage->required_features.glsl_versiontype==Stage::VERTEX && var.interface=="in") interface = "attribute";