Create SkSLOperators, centralize functionality

Change-Id: I3593e7ab0caac2fd572346038cbc8ff63e6fe970
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/366406
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp
index 37d8d20..cd67ac9 100644
--- a/src/sksl/SkSLMetalCodeGenerator.cpp
+++ b/src/sksl/SkSLMetalCodeGenerator.cpp
@@ -25,7 +25,7 @@
 const char* MetalCodeGenerator::OperatorName(Token::Kind op) {
     switch (op) {
         case Token::Kind::TK_LOGICALXOR:  return "!=";
-        default:                          return Compiler::OperatorName(op);
+        default:                          return Operators::OperatorName(op);
     }
 }
 
@@ -271,7 +271,7 @@
         if (param->modifiers().fFlags & Modifiers::kIn_Flag) {
             this->write(" = ");
             fIgnoreVariableReferenceModifiers = true;
-            this->writeExpression(*arguments[index], kAssignment_Precedence);
+            this->writeExpression(*arguments[index], Precedence::kAssignment);
             fIgnoreVariableReferenceModifiers = false;
         }
 
@@ -305,7 +305,7 @@
         }
         // outParam.zyx = _var2;
         fIgnoreVariableReferenceModifiers = true;
-        this->writeExpression(*arguments[index], kAssignment_Precedence);
+        this->writeExpression(*arguments[index], Precedence::kAssignment);
         fIgnoreVariableReferenceModifiers = false;
         this->write(" = _var");
         this->write(to_string(index));
@@ -381,9 +381,9 @@
         separator = ", ";
 
         if (outVars[i]) {
-            this->writeExpression(*outVars[i], kSequence_Precedence);
+            this->writeExpression(*outVars[i], Precedence::kSequence);
         } else {
-            this->writeExpression(*arguments[i], kSequence_Precedence);
+            this->writeExpression(*arguments[i], Precedence::kSequence);
         }
     }
     this->write(")");
@@ -513,7 +513,7 @@
     for (const std::unique_ptr<Expression>& arg : arguments) {
         this->write(separator);
         separator = ", ";
-        this->writeExpression(*arg, kSequence_Precedence);
+        this->writeExpression(*arg, Precedence::kSequence);
     }
     this->write(")");
 }
@@ -522,9 +522,9 @@
     const ExpressionArray& arguments = c.arguments();
     switch (kind) {
         case kTexture_IntrinsicKind: {
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write(".sample(");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write(SAMPLER_SUFFIX);
             this->write(", ");
             const Type& arg1Type = arguments[1]->type();
@@ -532,11 +532,11 @@
                 // have to store the vector in a temp variable to avoid double evaluating it
                 String tmpVar = this->getTempVariable(arg1Type);
                 this->write("(" + tmpVar + " = ");
-                this->writeExpression(*arguments[1], kSequence_Precedence);
+                this->writeExpression(*arguments[1], Precedence::kSequence);
                 this->write(", " + tmpVar + ".xy / " + tmpVar + ".z))");
             } else {
                 SkASSERT(arg1Type == *fContext.fTypes.fFloat2);
-                this->writeExpression(*arguments[1], kSequence_Precedence);
+                this->writeExpression(*arguments[1], Precedence::kSequence);
                 this->write(")");
             }
             break;
@@ -546,9 +546,9 @@
             String tmpX = this->getTempVariable(arguments[0]->type());
             String tmpY = this->getTempVariable(arguments[1]->type());
             this->write("(" + tmpX + " = ");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write(", " + tmpY + " = ");
-            this->writeExpression(*arguments[1], kSequence_Precedence);
+            this->writeExpression(*arguments[1], Precedence::kSequence);
             this->write(", " + tmpX + " - " + tmpY + " * floor(" + tmpX + " / " + tmpY + "))");
             break;
         }
@@ -556,9 +556,9 @@
         case kDistance_IntrinsicKind: {
             if (arguments[0]->type().columns() == 1) {
                 this->write("abs(");
-                this->writeExpression(*arguments[0], kAdditive_Precedence);
+                this->writeExpression(*arguments[0], Precedence::kAdditive);
                 this->write(" - ");
-                this->writeExpression(*arguments[1], kAdditive_Precedence);
+                this->writeExpression(*arguments[1], Precedence::kAdditive);
                 this->write(")");
             } else {
                 this->writeSimpleIntrinsic(c);
@@ -568,9 +568,9 @@
         case kDot_IntrinsicKind: {
             if (arguments[0]->type().columns() == 1) {
                 this->write("(");
-                this->writeExpression(*arguments[0], kMultiplicative_Precedence);
+                this->writeExpression(*arguments[0], Precedence::kMultiplicative);
                 this->write(" * ");
-                this->writeExpression(*arguments[1], kMultiplicative_Precedence);
+                this->writeExpression(*arguments[1], Precedence::kMultiplicative);
                 this->write(")");
             } else {
                 this->writeSimpleIntrinsic(c);
@@ -581,11 +581,11 @@
             if (arguments[0]->type().columns() == 1) {
                 // ((((Nref) * (I) < 0) ? 1 : -1) * (N))
                 this->write("((((");
-                this->writeExpression(*arguments[2], kSequence_Precedence);
+                this->writeExpression(*arguments[2], Precedence::kSequence);
                 this->write(") * (");
-                this->writeExpression(*arguments[1], kSequence_Precedence);
+                this->writeExpression(*arguments[1], Precedence::kSequence);
                 this->write(") < 0) ? 1 : -1) * (");
-                this->writeExpression(*arguments[0], kSequence_Precedence);
+                this->writeExpression(*arguments[0], Precedence::kSequence);
                 this->write("))");
             } else {
                 this->writeSimpleIntrinsic(c);
@@ -594,32 +594,32 @@
         }
         case kLength_IntrinsicKind: {
             this->write(arguments[0]->type().columns() == 1 ? "abs(" : "length(");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write(")");
             break;
         }
         case kNormalize_IntrinsicKind: {
             this->write(arguments[0]->type().columns() == 1 ? "sign(" : "normalize(");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write(")");
             break;
         }
         case kBitcast_IntrinsicKind: {
             this->write(this->getBitcastIntrinsic(c.type()));
             this->write("(");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write(")");
             break;
         }
         case kDegrees_IntrinsicKind: {
             this->write("((");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write(") * 57.2957795)");
             break;
         }
         case kRadians_IntrinsicKind: {
             this->write("((");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write(") * 0.0174532925)");
             break;
         }
@@ -660,11 +660,11 @@
 
                 // (_skTempI = ...
                 this->write("(" + tmpI + " = ");
-                this->writeExpression(*arguments[0], kSequence_Precedence);
+                this->writeExpression(*arguments[0], Precedence::kSequence);
 
                 // , _skTempN = ...
                 this->write(", " + tmpN + " = ");
-                this->writeExpression(*arguments[1], kSequence_Precedence);
+                this->writeExpression(*arguments[1], Precedence::kSequence);
 
                 // , _skTempI - 2 * _skTempN * _skTempI * _skTempN)
                 this->write(", " + tmpI + " - 2 * " + tmpN + " * " + tmpI + " * " + tmpN + ")");
@@ -678,11 +678,11 @@
                 // Metal does implement refract for vectors; rather than reimplementing refract from
                 // scratch, we can replace the call with `refract(float2(I,0), float2(N,0), eta).x`.
                 this->write("(refract(float2(");
-                this->writeExpression(*arguments[0], kSequence_Precedence);
+                this->writeExpression(*arguments[0], Precedence::kSequence);
                 this->write(", 0), float2(");
-                this->writeExpression(*arguments[1], kSequence_Precedence);
+                this->writeExpression(*arguments[1], Precedence::kSequence);
                 this->write(", 0), ");
-                this->writeExpression(*arguments[2], kSequence_Precedence);
+                this->writeExpression(*arguments[2], Precedence::kSequence);
                 this->write(").x)");
             } else {
                 this->writeSimpleIntrinsic(c);
@@ -696,7 +696,7 @@
         }
         case kBitCount_IntrinsicKind: {
             this->write("popcount(");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write(")");
             break;
         }
@@ -712,7 +712,7 @@
             this->write("(");
             this->write(skTemp);
             this->write(" = (");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write("), select(ctz(");
             this->write(skTemp);
             this->write("), ");
@@ -737,7 +737,7 @@
             this->write("(");
             this->write(skTemp1);
             this->write(" = (");
-            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->writeExpression(*arguments[0], Precedence::kSequence);
             this->write("), ");
 
             // Signed input types might be negative; we need another helper variable to negate the
@@ -784,7 +784,7 @@
         case kCompareLessThanEqual_IntrinsicKind:
         case kCompareNotEqual_IntrinsicKind: {
             this->write("(");
-            this->writeExpression(*c.arguments()[0], kRelational_Precedence);
+            this->writeExpression(*c.arguments()[0], Precedence::kRelational);
             switch (kind) {
                 case kCompareEqual_IntrinsicKind:
                     this->write(" == ");
@@ -807,7 +807,7 @@
                 default:
                     SK_ABORT("unsupported comparison intrinsic kind");
             }
-            this->writeExpression(*c.arguments()[1], kRelational_Precedence);
+            this->writeExpression(*c.arguments()[1], Precedence::kRelational);
             this->write(")");
             break;
         }
@@ -1055,7 +1055,7 @@
         for (const std::unique_ptr<Expression>& expr : c.arguments()) {
             this->write(separator);
             separator = ", ";
-            this->writeExpression(*expr, kSequence_Precedence);
+            this->writeExpression(*expr, Precedence::kSequence);
         }
         this->write(")");
         return;
@@ -1080,7 +1080,7 @@
             }
             scalarCount += argType.columns();
         }
-        this->writeExpression(*arg, kSequence_Precedence);
+        this->writeExpression(*arg, Precedence::kSequence);
         if (scalarCount && scalarCount == constructorType.rows()) {
             this->write(")");
             scalarCount = 0;
@@ -1145,16 +1145,16 @@
 }
 
 void MetalCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
-    this->writeExpression(*expr.base(), kPostfix_Precedence);
+    this->writeExpression(*expr.base(), Precedence::kPostfix);
     this->write("[");
-    this->writeExpression(*expr.index(), kTopLevel_Precedence);
+    this->writeExpression(*expr.index(), Precedence::kTopLevel);
     this->write("]");
 }
 
 void MetalCodeGenerator::writeFieldAccess(const FieldAccess& f) {
     const Type::Field* field = &f.base()->type().fields()[f.fieldIndex()];
     if (FieldAccess::OwnerKind::kDefault == f.ownerKind()) {
-        this->writeExpression(*f.base(), kPostfix_Precedence);
+        this->writeExpression(*f.base(), Precedence::kPostfix);
         this->write(".");
     }
     switch (field->fModifiers.fLayout.fBuiltin) {
@@ -1176,7 +1176,7 @@
 }
 
 void MetalCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
-    this->writeExpression(*swizzle.base(), kPostfix_Precedence);
+    this->writeExpression(*swizzle.base(), Precedence::kPostfix);
     this->write(".");
     for (int c : swizzle.components()) {
         SkASSERT(c >= 0 && c <= 3);
@@ -1184,43 +1184,6 @@
     }
 }
 
-MetalCodeGenerator::Precedence MetalCodeGenerator::GetBinaryPrecedence(Token::Kind op) {
-    switch (op) {
-        case Token::Kind::TK_STAR:         // fall through
-        case Token::Kind::TK_SLASH:        // fall through
-        case Token::Kind::TK_PERCENT:      return MetalCodeGenerator::kMultiplicative_Precedence;
-        case Token::Kind::TK_PLUS:         // fall through
-        case Token::Kind::TK_MINUS:        return MetalCodeGenerator::kAdditive_Precedence;
-        case Token::Kind::TK_SHL:          // fall through
-        case Token::Kind::TK_SHR:          return MetalCodeGenerator::kShift_Precedence;
-        case Token::Kind::TK_LT:           // fall through
-        case Token::Kind::TK_GT:           // fall through
-        case Token::Kind::TK_LTEQ:         // fall through
-        case Token::Kind::TK_GTEQ:         return MetalCodeGenerator::kRelational_Precedence;
-        case Token::Kind::TK_EQEQ:         // fall through
-        case Token::Kind::TK_NEQ:          return MetalCodeGenerator::kEquality_Precedence;
-        case Token::Kind::TK_BITWISEAND:   return MetalCodeGenerator::kBitwiseAnd_Precedence;
-        case Token::Kind::TK_BITWISEXOR:   return MetalCodeGenerator::kBitwiseXor_Precedence;
-        case Token::Kind::TK_BITWISEOR:    return MetalCodeGenerator::kBitwiseOr_Precedence;
-        case Token::Kind::TK_LOGICALAND:   return MetalCodeGenerator::kLogicalAnd_Precedence;
-        case Token::Kind::TK_LOGICALXOR:   return MetalCodeGenerator::kLogicalXor_Precedence;
-        case Token::Kind::TK_LOGICALOR:    return MetalCodeGenerator::kLogicalOr_Precedence;
-        case Token::Kind::TK_EQ:           // fall through
-        case Token::Kind::TK_PLUSEQ:       // fall through
-        case Token::Kind::TK_MINUSEQ:      // fall through
-        case Token::Kind::TK_STAREQ:       // fall through
-        case Token::Kind::TK_SLASHEQ:      // fall through
-        case Token::Kind::TK_PERCENTEQ:    // fall through
-        case Token::Kind::TK_SHLEQ:        // fall through
-        case Token::Kind::TK_SHREQ:        // fall through
-        case Token::Kind::TK_BITWISEANDEQ: // fall through
-        case Token::Kind::TK_BITWISEXOREQ: // fall through
-        case Token::Kind::TK_BITWISEOREQ:  return MetalCodeGenerator::kAssignment_Precedence;
-        case Token::Kind::TK_COMMA:        return MetalCodeGenerator::kSequence_Precedence;
-        default: SK_ABORT("unsupported binary operator");
-    }
-}
-
 void MetalCodeGenerator::writeMatrixTimesEqualHelper(const Type& left, const Type& right,
                                                      const Type& result) {
     String key = "TimesEqual" + this->typeName(left) + this->typeName(right);
@@ -1243,7 +1206,7 @@
     const Type& leftType = left.type();
     const Type& rightType = right.type();
     Token::Kind op = b.getOperator();
-    Precedence precedence = GetBinaryPrecedence(b.getOperator());
+    Precedence precedence = Operators::GetBinaryPrecedence(b.getOperator());
     bool needParens = precedence >= parentPrecedence;
     switch (op) {
         case Token::Kind::TK_EQEQ:
@@ -1268,7 +1231,7 @@
         this->writeMatrixTimesEqualHelper(leftType, rightType, b.type());
     }
     this->writeExpression(left, precedence);
-    if (op != Token::Kind::TK_EQ && Compiler::IsAssignment(op) &&
+    if (op != Token::Kind::TK_EQ && Operators::IsAssignment(op) &&
         left.kind() == Expression::Kind::kSwizzle && !left.hasSideEffects()) {
         // This doesn't compile in Metal:
         // float4 x = float4(1);
@@ -1277,7 +1240,7 @@
         // but switching it to x.xy = x.xy * float2x2(...) fixes it. We perform this tranformation
         // as long as the LHS has no side effects, and hope for the best otherwise.
         this->write(" = ");
-        this->writeExpression(left, kAssignment_Precedence);
+        this->writeExpression(left, Precedence::kAssignment);
         this->write(" ");
         String opName = OperatorName(op);
         SkASSERT(opName.endsWith("="));
@@ -1294,39 +1257,39 @@
 
 void MetalCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
                                                Precedence parentPrecedence) {
-    if (kTernary_Precedence >= parentPrecedence) {
+    if (Precedence::kTernary >= parentPrecedence) {
         this->write("(");
     }
-    this->writeExpression(*t.test(), kTernary_Precedence);
+    this->writeExpression(*t.test(), Precedence::kTernary);
     this->write(" ? ");
-    this->writeExpression(*t.ifTrue(), kTernary_Precedence);
+    this->writeExpression(*t.ifTrue(), Precedence::kTernary);
     this->write(" : ");
-    this->writeExpression(*t.ifFalse(), kTernary_Precedence);
-    if (kTernary_Precedence >= parentPrecedence) {
+    this->writeExpression(*t.ifFalse(), Precedence::kTernary);
+    if (Precedence::kTernary >= parentPrecedence) {
         this->write(")");
     }
 }
 
 void MetalCodeGenerator::writePrefixExpression(const PrefixExpression& p,
                                               Precedence parentPrecedence) {
-    if (kPrefix_Precedence >= parentPrecedence) {
+    if (Precedence::kPrefix >= parentPrecedence) {
         this->write("(");
     }
     this->write(OperatorName(p.getOperator()));
-    this->writeExpression(*p.operand(), kPrefix_Precedence);
-    if (kPrefix_Precedence >= parentPrecedence) {
+    this->writeExpression(*p.operand(), Precedence::kPrefix);
+    if (Precedence::kPrefix >= parentPrecedence) {
         this->write(")");
     }
 }
 
 void MetalCodeGenerator::writePostfixExpression(const PostfixExpression& p,
                                                Precedence parentPrecedence) {
-    if (kPostfix_Precedence >= parentPrecedence) {
+    if (Precedence::kPostfix >= parentPrecedence) {
         this->write("(");
     }
-    this->writeExpression(*p.operand(), kPostfix_Precedence);
+    this->writeExpression(*p.operand(), Precedence::kPostfix);
     this->write(OperatorName(p.getOperator()));
-    if (kPostfix_Precedence >= parentPrecedence) {
+    if (Precedence::kPostfix >= parentPrecedence) {
         this->write(")");
     }
 }
@@ -1686,7 +1649,7 @@
 }
 
 void MetalCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
-    this->writeExpression(value, kTopLevel_Precedence);
+    this->writeExpression(value, Precedence::kTopLevel);
 }
 
 void MetalCodeGenerator::writeName(const String& name) {
@@ -1717,7 +1680,7 @@
             this->writeBlock(s.as<Block>());
             break;
         case Statement::Kind::kExpression:
-            this->writeExpression(*s.as<ExpressionStatement>().expression(), kTopLevel_Precedence);
+            this->writeExpression(*s.as<ExpressionStatement>().expression(), Precedence::kTopLevel);
             this->write(";");
             break;
         case Statement::Kind::kReturn:
@@ -1779,7 +1742,7 @@
 
 void MetalCodeGenerator::writeIfStatement(const IfStatement& stmt) {
     this->write("if (");
-    this->writeExpression(*stmt.test(), kTopLevel_Precedence);
+    this->writeExpression(*stmt.test(), Precedence::kTopLevel);
     this->write(") ");
     this->writeStatement(*stmt.ifTrue());
     if (stmt.ifFalse()) {
@@ -1792,7 +1755,7 @@
     // Emit loops of the form 'for(;test;)' as 'while(test)', which is probably how they started
     if (!f.initializer() && f.test() && !f.next()) {
         this->write("while (");
-        this->writeExpression(*f.test(), kTopLevel_Precedence);
+        this->writeExpression(*f.test(), Precedence::kTopLevel);
         this->write(") ");
         this->writeStatement(*f.statement());
         return;
@@ -1805,11 +1768,11 @@
         this->write("; ");
     }
     if (f.test()) {
-        this->writeExpression(*f.test(), kTopLevel_Precedence);
+        this->writeExpression(*f.test(), Precedence::kTopLevel);
     }
     this->write("; ");
     if (f.next()) {
-        this->writeExpression(*f.next(), kTopLevel_Precedence);
+        this->writeExpression(*f.next(), Precedence::kTopLevel);
     }
     this->write(") ");
     this->writeStatement(*f.statement());
@@ -1819,19 +1782,19 @@
     this->write("do ");
     this->writeStatement(*d.statement());
     this->write(" while (");
-    this->writeExpression(*d.test(), kTopLevel_Precedence);
+    this->writeExpression(*d.test(), Precedence::kTopLevel);
     this->write(");");
 }
 
 void MetalCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
     this->write("switch (");
-    this->writeExpression(*s.value(), kTopLevel_Precedence);
+    this->writeExpression(*s.value(), Precedence::kTopLevel);
     this->writeLine(") {");
     fIndentation++;
     for (const std::unique_ptr<SwitchCase>& c : s.cases()) {
         if (c->value()) {
             this->write("case ");
-            this->writeExpression(*c->value(), kTopLevel_Precedence);
+            this->writeExpression(*c->value(), Precedence::kTopLevel);
             this->writeLine(":");
         } else {
             this->writeLine("default:");
@@ -1866,7 +1829,7 @@
         if (r.expression()) {
             if (r.expression()->type() == *fContext.fTypes.fHalf4) {
                 this->write("_out.sk_FragColor = ");
-                this->writeExpression(*r.expression(), kTopLevel_Precedence);
+                this->writeExpression(*r.expression(), Precedence::kTopLevel);
                 this->writeLine(";");
             } else {
                 fErrors.error(r.fOffset, "Metal does not support returning '" +
@@ -1880,7 +1843,7 @@
     this->write("return");
     if (r.expression()) {
         this->write(" ");
-        this->writeExpression(*r.expression(), kTopLevel_Precedence);
+        this->writeExpression(*r.expression(), Precedence::kTopLevel);
     }
     this->write(";");
 }