From bde40be11da83206f3d33a8225963d47a413662e Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 13 Mar 2021 21:15:07 +0200 Subject: [PATCH] Move parenthesizing expressions to Formatter --- source/glsl/optimize.cpp | 57 +++++++++++----------------------------- source/glsl/optimize.h | 7 ++--- source/glsl/output.cpp | 52 +++++++++++++++++++++++++++++------- source/glsl/output.h | 1 + 4 files changed, 61 insertions(+), 56 deletions(-) diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index 8f6b2745..0d18b76c 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -268,9 +268,6 @@ ExpressionInliner::ExpressionInfo::ExpressionInfo(): expression(0), assign_scope(0), inline_point(0), - inner_oper(0), - outer_oper(0), - inline_on_rhs(false), trivial(false), available(true) { } @@ -292,7 +289,7 @@ bool ExpressionInliner::apply(Stage &s) return r_any_inlined; } -void ExpressionInliner::visit_and_record(RefPtr &ptr, const Operator *outer_oper, bool on_rhs) +void ExpressionInliner::visit_and_record(RefPtr &ptr) { r_ref_info = 0; ptr->visit(*this); @@ -309,39 +306,19 @@ void ExpressionInliner::visit_and_record(RefPtr &ptr, const Operator return; } - r_ref_info->outer_oper = outer_oper; if(r_ref_info->trivial) - inline_expression(*r_ref_info->expression, ptr, outer_oper, r_ref_info->inner_oper, on_rhs); + inline_expression(*r_ref_info->expression, ptr); else - { /* Record the inline point for a non-trivial expression but don't inline it yet. It might turn out it shouldn't be inlined after all. */ r_ref_info->inline_point = &ptr; - r_ref_info->inline_on_rhs = on_rhs; - } } r_ref_info = 0; } -void ExpressionInliner::inline_expression(Expression &expr, RefPtr &ptr, const Operator *outer_oper, const Operator *inner_oper, bool on_rhs) +void ExpressionInliner::inline_expression(Expression &expr, RefPtr &ptr) { - unsigned outer_precedence = (outer_oper ? outer_oper->precedence : 20); - unsigned inner_precedence = (inner_oper ? inner_oper->precedence : 0); - - bool needs_parentheses = (inner_precedence>=outer_precedence); - if(inner_oper && inner_oper==outer_oper) - // Omit parentheses if the operator's natural grouping works out. - needs_parentheses = (inner_oper->assoc!=Operator::ASSOCIATIVE && on_rhs!=(inner_oper->assoc==Operator::RIGHT_TO_LEFT)); - - if(needs_parentheses) - { - RefPtr parexpr = new ParenthesizedExpression; - parexpr->expression = expr.clone(); - ptr = parexpr; - } - else - ptr = expr.clone(); - + ptr = expr.clone(); r_any_inlined = true; } @@ -355,7 +332,7 @@ void ExpressionInliner::visit(Block &block) for(; (j!=expressions.end() && j->first.declaration==i->second); ) { if(j->second.expression && j->second.inline_point) - inline_expression(*j->second.expression, *j->second.inline_point, j->second.outer_oper, j->second.inner_oper, j->second.inline_on_rhs); + inline_expression(*j->second.expression, *j->second.inline_point); expressions.erase(j++); } @@ -371,7 +348,7 @@ void ExpressionInliner::visit(Block &block) void ExpressionInliner::visit(RefPtr &expr) { - visit_and_record(expr, 0, false); + visit_and_record(expr); } void ExpressionInliner::visit(VariableReference &var) @@ -396,14 +373,14 @@ void ExpressionInliner::visit(VariableReference &var) void ExpressionInliner::visit(MemberAccess &memacc) { - visit_and_record(memacc.left, memacc.oper, false); + visit_and_record(memacc.left); r_oper = memacc.oper; r_trivial = false; } void ExpressionInliner::visit(Swizzle &swizzle) { - visit_and_record(swizzle.left, swizzle.oper, false); + visit_and_record(swizzle.left); r_oper = swizzle.oper; r_trivial = false; } @@ -411,17 +388,17 @@ void ExpressionInliner::visit(Swizzle &swizzle) void ExpressionInliner::visit(UnaryExpression &unary) { SetFlag set_target(mutating, mutating || unary.oper->token[1]=='+' || unary.oper->token[1]=='-'); - visit_and_record(unary.expression, unary.oper, false); + visit_and_record(unary.expression); r_oper = unary.oper; r_trivial = false; } void ExpressionInliner::visit(BinaryExpression &binary) { - visit_and_record(binary.left, binary.oper, false); + visit_and_record(binary.left); { SetFlag clear_target(mutating, false); - visit_and_record(binary.right, binary.oper, true); + visit_and_record(binary.right); } r_oper = binary.oper; r_trivial = false; @@ -431,10 +408,10 @@ void ExpressionInliner::visit(Assignment &assign) { { SetFlag set_target(mutating); - visit_and_record(assign.left, assign.oper, false); + visit_and_record(assign.left); } r_oper = 0; - visit_and_record(assign.right, assign.oper, true); + visit_and_record(assign.right); map::iterator i = expressions.find(assign.target); if(i!=expressions.end()) @@ -444,7 +421,6 @@ void ExpressionInliner::visit(Assignment &assign) i->second.expression = (assign.self_referencing ? 0 : assign.right.get()); i->second.assign_scope = current_block; i->second.inline_point = 0; - i->second.inner_oper = r_oper; i->second.available = true; } @@ -454,9 +430,9 @@ void ExpressionInliner::visit(Assignment &assign) void ExpressionInliner::visit(TernaryExpression &ternary) { - visit_and_record(ternary.condition, ternary.oper, false); - visit_and_record(ternary.true_expr, ternary.oper, false); - visit_and_record(ternary.false_expr, ternary.oper, true); + visit_and_record(ternary.condition); + visit_and_record(ternary.true_expr); + visit_and_record(ternary.false_expr); r_oper = ternary.oper; r_trivial = false; } @@ -491,7 +467,6 @@ void ExpressionInliner::visit(VariableDeclaration &var) will have their values change throughout the iteration. */ info.expression = (iteration_init ? 0 : var.init_expression.get()); info.assign_scope = current_block; - info.inner_oper = r_oper; info.trivial = r_trivial; } } diff --git a/source/glsl/optimize.h b/source/glsl/optimize.h index 0604a39c..ca22c9d8 100644 --- a/source/glsl/optimize.h +++ b/source/glsl/optimize.h @@ -101,9 +101,6 @@ private: Expression *expression; Block *assign_scope; RefPtr *inline_point; - const Operator *inner_oper; - const Operator *outer_oper; - bool inline_on_rhs; bool trivial; bool available; @@ -125,8 +122,8 @@ public: bool apply(Stage &); private: - void visit_and_record(RefPtr &, const Operator *, bool); - void inline_expression(Expression &, RefPtr &, const Operator *, const Operator *, bool); + void visit_and_record(RefPtr &); + void inline_expression(Expression &, RefPtr &); virtual void visit(Block &); virtual void visit(RefPtr &); virtual void visit(VariableReference &); diff --git a/source/glsl/output.cpp b/source/glsl/output.cpp index 35c52fec..f1e9b4be 100644 --- a/source/glsl/output.cpp +++ b/source/glsl/output.cpp @@ -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,35 +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); + 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) { - ternary.condition->visit(*this); + visit_expression(*ternary.condition, ternary.oper, false); append(ternary.oper->token); - ternary.true_expr->visit(*this); + visit_expression(*ternary.true_expr, ternary.oper, false); if(ternary.oper->token2) append(ternary.oper->token2); - ternary.false_expr->visit(*this); + visit_expression(*ternary.false_expr, ternary.oper, true); } void Formatter::visit(FunctionCall &call) diff --git a/source/glsl/output.h b/source/glsl/output.h index d872dabe..efcde5d6 100644 --- a/source/glsl/output.h +++ b/source/glsl/output.h @@ -33,6 +33,7 @@ private: void set_source(unsigned, unsigned); virtual void visit(Block &); + void visit_expression(Expression &, const Operator *, bool); virtual void visit(Literal &); virtual void visit(ParenthesizedExpression &); virtual void visit(VariableReference &); -- 2.43.0